I had to fight with this issue yesterday and I've also ended up to write my custom extension class.
As you can see by looking at the code below and comparing it with the accepted answer, I tried to tweak the suggestion a little bit more in order to have a more versatile class: this way you can set a precise timeout either upon instancing the object or right before using a method that uses the internal WebRequest
handler.
using System;
using System.Net;
namespace Ryadel.Components.Web
{
/// <summary>
/// An extension of the standard System.Net.WebClient
/// featuring a customizable constructor and [Timeout] property.
/// </summary>
public class RyadelWebClient : WebClient
{
/// <summary>
/// Default constructor (30000 ms timeout)
/// NOTE: timeout can be changed later on using the [Timeout] property.
/// </summary>
public RyadelWebClient() : this(30000) { }
/// <summary>
/// Constructor with customizable timeout
/// </summary>
/// <param name="timeout">
/// Web request timeout (in milliseconds)
/// </param>
public RyadelWebClient(int timeout)
{
Timeout = timeout;
}
#region Methods
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest w = base.GetWebRequest(uri);
w.Timeout = Timeout;
((HttpWebRequest)w).ReadWriteTimeout = Timeout;
return w;
}
#endregion
/// <summary>
/// Web request timeout (in milliseconds)
/// </summary>
public int Timeout { get; set; }
}
}
While I was there, I also took the chance to lower the default Timeout
value to 30
seconds, as 100
seemed way too much for me.
In case you need additional info regarding this class or how to use it, check out this post I wrote on my blog.