WebClient.DownloadFileTaskAsync()从未实际超时吗?

时间:2015-08-31 22:06:43

标签: c# .net async-await webclient webclient-download

在异步前的日子里,人们想知道如何在WebClient上设置超时,答案只是扩展基类并覆盖GetWebRequest()并在那里设置超时。

protected override WebRequest GetWebRequest(Uri address)
{
    // NOTE: this override has no affect if the Async methods are used!!!
    WebRequest request = base.GetWebRequest(address);
    ((HttpWebRequest)request).Timeout = 20 * 60 * 1000;
    ((HttpWebRequest)request).ReadWriteTimeout = 20 * 60 * 1000;
    return request;
}

假设人们需要更长的超时。

然后通过添加xyzTaskAsync()方法,人们想知道如何设置超时,答案是使用由本地计时器驱动的CancellationToken。

所以我猜这个假设是人们需要在给定时间后结束请求。

所以这是否意味着 DownloadFileTaskAsync()DownloadStringTaskAsync() 永远不会超时?超时故障不是任何网络操作的固有部分吗?

我使用GetWebRequest()覆盖来设置一个非常小的超时值。它会在调用非异步方法时抛出超时异常,但在调用异步方法时则不会抛出异常。

我已经反编译了System.Net库,但异步方法似乎调用了一些不容易被发现的缓存匿名lambdas。

是否有人确切知道DownloadXyzTaskAsync()方法是否以相当于无限超时值的方式执行?

1 个答案:

答案 0 :(得分:3)

同步操作是阻塞的,这意味着线程在某种等待句柄上被阻止。等待可以是无限的(如果操作本身没有结束则是无限的),或者等待可以接收某种超时,之后它会解除阻塞和超时。

异步操作本身就是异步操作,没有任何活动部分执行某些操作。没有线程被阻止或类似的东西。这意味着,如果没有告诉它,它本身就不能真正超时或取消,即使这样,操作也只是放弃而不是取消。这通常是CancellationToken(在超时后可能会或可能不会通过计时器发出信号)。

因此,这种(以及任何其他类型的)异步操作需要某些东西(即CancellationToken)能够超时。确实,库可以在内部使用计时器,但很少在.Net中完成,因为它是意外的,你可以自己取消CancellationToken

因此,在这种特定情况下,通常,异步方法通常不会受配置的超时影响。 SocketTcpClientUdpClient等情况也是如此。

现在,如果您想要从HttpWebRequest的实际代码进行确认,您可以看到超时用于创建计时器队列here。该队列用于在GetResponse中创建超时计时器,但从不在BeginGetResponse中创建。这是DownloadXXXAsync中使用的DownloadXXXTaskAsync中使用的异步选项。