Problem
I’m trying to download data from a client to my local system (programatically), however their webserver is extremely slow, causing my WebClient object to time out.
Here’s what I came up with:
WebClient webClient = new WebClient();
webClient.Encoding = Encoding.UTF8;
webClient.DownloadFile(downloadUrl, downloadFile);
Is there a way to make this object have an indefinite timeout? Can somebody provide me an example of a different way to do this if this isn’t possible?
In a browser, the URL works perfectly; it simply takes roughly 3 minutes to load.
Asked by Ryall
Solution #1
You can customize the timeout by inheriting the original WebClient class and overriding the webrequest getter, as shown in the example below.
In my situation, MyWebClient was a private class:
private class MyWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest w = base.GetWebRequest(uri);
w.Timeout = 20 * 60 * 1000;
return w;
}
}
Answered by kisp
Solution #2
Although the original approach did not work for me, here is some code that did.
private class WebClient : System.Net.WebClient
{
public int Timeout { get; set; }
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest lWebRequest = base.GetWebRequest(uri);
lWebRequest.Timeout = Timeout;
((HttpWebRequest)lWebRequest).ReadWriteTimeout = Timeout;
return lWebRequest;
}
}
private string GetRequest(string aURL)
{
using (var lWebClient = new WebClient())
{
lWebClient.Timeout = 600 * 60 * 1000;
return lWebClient.DownloadString(aURL);
}
}
Answered by Davinci Jeremie
Solution #3
Because you can’t set the timeout on WebClient without extending it, you’ll need to use HttpWebRequest instead (even though it uses the HttpWebRequest). Instead, you can use the HttpWebRequest to set the timeout.
Answered by Fenton
Solution #4
When I couldn’t get the w.Timeout code to function after removing the network cable, it simply wouldn’t time out, so I switched to HttpWebRequest, which now works.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(downloadUrl);
request.Timeout = 10000;
request.ReadWriteTimeout = 10000;
var wresp = (HttpWebResponse)request.GetResponse();
using (Stream file = File.OpenWrite(downloadFile))
{
wresp.GetResponseStream().CopyTo(file);
}
Answered by themullet
Solution #5
The offered solutions will not work for anyone who requires a WebClient with a timeout that works with async/task methods. Here’s what actually works:
public class WebClientWithTimeout : WebClient
{
//10 secs default
public int Timeout { get; set; } = 10000;
//for sync requests
protected override WebRequest GetWebRequest(Uri uri)
{
var w = base.GetWebRequest(uri);
w.Timeout = Timeout; //10 seconds timeout
return w;
}
//the above will not work for async requests :(
//let's create a workaround by hiding the method
//and creating our own version of DownloadStringTaskAsync
public new async Task<string> DownloadStringTaskAsync(Uri address)
{
var t = base.DownloadStringTaskAsync(address);
if(await Task.WhenAny(t, Task.Delay(Timeout)) != t) //time out!
{
CancelAsync();
}
return await t;
}
}
I detailed the workaround in this blog post.
Answered by Alex from Jitbit
Post is based on https://stackoverflow.com/questions/1789627/how-to-change-the-timeout-on-a-net-webclient-object