问题
In the pre-async days, people wanted to know how to set the timeout on WebClient
and the answer was simply to extend the base class and override GetWebRequest()
and set the timeout there.
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;
}
The assumption was that people needed a longer timeouts.
Then with the addition of the xyzTaskAsync()
methods, people wanted to know how to set the timeout, and the answer was to use a CancellationToken driven by a local timer.
So I guess the assumption was that people needed the request to end after a given time.
So does this mean that DownloadFileTaskAsync()
or DownloadStringTaskAsync()
never timeout by themselves? Isn't a timeout failure an inherent part of any network operation?
I've used the GetWebRequest()
override to set a very small timeout value. It throws the timeout exception when non-async methods are called, but not when the async methods are called.
I've decompiled the System.Net library, but the async methods seem to invoke some cached anonymous lambdas that are not easily discoverable.
Does anyone know with certainty if the DownloadXyzTaskAsync()
methods execute with the equivalent of an infinite timeout value?
回答1:
Synchronous operations are blocking, that means a thread is blocked on some kind of wait handle. That wait can be unlimited (and so infinite if the operation itself doesn't end) or that wait can receive some kind of timeout after which it unblocks and timeouts.
An asynchronous operation, by inherently being asynchronous, doesn't have any active part doing something. There's no thread being blocked or anything similar. That means that it inherently can't really timeout or cancel without something telling it to, and even then the operation is merely abandoned and not cancelled. That something is usually a CancellationToken
(that may or may not be signaled with a timer after a timeout).
So, this (and any other kind of) asynchronous operation needs something (i.e. a CancellationToken
) to be able to timeout. It's true that the library can use a timer internally but that is rarely done in .Net as it's unexpected and you can do that yourself with a self cancelling CancellationToken
.
So, in this specific case and in general, async methods aren't usually affected by a configured timeout. That's also the case with Socket
, TcpClient
, UdpClient
, etc.
Now, if you want confirmation from the actual code of HttpWebRequest
you can see that the timeout is used to create a timer queue here. That queue is used to create a timeout timer in GetResponse but never in BeginGetResponse. That is the asynchronous option used in the DownloadXXXAsync
which is used in DownloadXXXTaskAsync
.
来源:https://stackoverflow.com/questions/32320683/does-webclient-downloadfiletaskasync-never-actually-timeout