我是一个使用.TAP 模式API编写的网络爬虫HttpWebRequest
。
我想从中下载一些东西,http://somedomain.tld
但我最终可能会发送相当多的请求。我不知道是否somedomain.tld
会及时回复,我希望每个请求不超过 10 秒以完成发回回复。我还想利用ServicePoint
该域强制执行的连接限制。
所以我需要能够根据请求超时。通常,我会从 a 获得取消令牌CancellationTokenSource
:
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10d))
并将其提供给我的异步操作,也许还注册一个调用的取消回调myWebRequest.Abort()
,所以我最终得到一个看起来像这样的(简化)方法:
public async Task<byte[]> GetResponseData(Uri uri, CancellationToken ct)
{
var wr = (HttpWebRequest)WebRequest.Create(uri);
ct.Register(wr.Abort);
using(var response = await wr.GetResponseAsync())
using(var ms = new MemoryStream())
using(var responseStream = response.GetResponseStream())
{
await responseStream.CopyToAsync(ms,4096,ct);
return ms.ToArray();
}
}
到目前为止,一切都很好。
让我稍微限制一下:
var uri = new Uri("http://somedomain.tld");
var sp = ServicePointManager.FindServicePoint(uri);
sp.ConnectionLimit = 1;
现在,ServicePoint
关联的实例somedomain.tld
一次只允许一个请求。
现在我同时发出两个请求,安全地知道这ServicePoint
将使目标域免受我的滥用:
var dataTasks = Enumerable.Range(0,2).Select(async _=>{
using(var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10d)))
{
return await GetResponseData(uri,cts.Token);
}
});
var datas = await Task.WhenAll(dataTasks);
现在,让我们假设第一个请求需要超过 10 秒才能完成......因为我已经限制ServicePoint
一次只触发一个请求,ServicePoint
当轮到触发第二个请求时,它已经被取消并且中止。
那么我怎么知道请求实际上是什么时候发送的呢?如何设置“知道”ServicePoint
与特定请求有关的操作的超时?