WebClient.DownloadFileTaskAsync() 真的不会超时吗?

Does WebClient.DownloadFileTaskAsync() never actually timeout?

在异步之前的日子里,人们想知道如何在 WebClient 上设置超时,答案只是扩展基础 class 并覆盖 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 库,但是异步方法似乎调用了一些不容易被发现的缓存匿名 lambda。

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

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

异步操作本质上是异步的,没有任何主动部分在做某事。没有线程被阻塞或类似情况。这意味着它本质上不能在没有任何指示的情况下真正超时或取消,即使这样操作也只是被放弃而不是取消。这通常是 CancellationToken(超时后可能会或可能不会用计时器发出信号)。

因此,此(以及任何其他类型的)异步操作需要一些东西(即 CancellationToken)才能超时。该库确实可以在内部使用计时器,但在 .Net 中很少这样做,因为这是意想不到的,您可以通过自我取消 CancellationToken.

自己做到这一点

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

现在,如果您想从 HttpWebRequest 的实际代码中确认,您可以看到超时用于创建计时器队列 here. That queue is used to create a timeout timer in GetResponse but never in BeginGetResponse。那就是在 DownloadXXXTaskAsync.

中使用的 DownloadXXXAsync 中使用的异步选项