How can I download a file using WebClient in C# with firing the eventhandlers and supporting the timeout property?
I'm developing a C# project to download the files from the internet.
I'll show the progresses of them while the downloads are going. And I should support the time-out property.
I've tried to use the WebClient class. There are DownloadFile() and DownloadFileAsync() functions.
- When I use DownloadFile() function, I can set the Timeout property, overriding the GetWebRequest() function. However, I can't fire the event handlers, so I can't show the progresses.
- When I use DownloadFileAsync() function, I can fire the event handlers, so I can show the progresses. But, in this case, I can't set the Timeout.
From the internet, I can find some articles about the way to set the timeout manually using threading.
However, I think that all of them are incorrect. They set the timeout during the entire download progress. But the downloading will be short or long according to the size of the file.
How can I solve this problem?
Per the MSDN documentation on HttpWebRequest, you need to implement this yourself using threading.
In the case of asynchronous requests, it is the responsibility of the client application to implement its own time-out mechanism. The following code example shows how to do it.
The above link actually gives a complete example of how to do this, using a thread pool and a ManualResetEvent (the example is about 50-100 lines of code).
Here is the crux of the above solution, with code quoted from the MSDN example.
Use the asynchronous BeginGetResponse.
IAsyncResult result= (IAsyncResult) myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback),myRequestState);
Use ThreadPool.RegisterWaitForSingleObject to implement the timeout.
ThreadPool.RegisterWaitForSingleObject (result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), myHttpWebRequest, DefaultTimeout, true);
Use the ManualResetEvent to hold the main thread until either the request is complete, or timed out.
public static ManualResetEvent allDone = new ManualResetEvent(false); allDone.WaitOne();
try to show this