Webclient在下载请求时没法设置请求超时时间和请求读写超时时间。WebClient在异步下载时遇到网络不通等问题时没有响应超时形成app挂起。 网络
1.Webclient请求超时设置
重写Webclient的GetWebRequest方法,为HttpWebRequest添加请求超时及读写超时 app
protected
override
WebRequest GetWebRequest(Uri address)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
request.Timeout = 1000 * Timeout;
request.ReadWriteTimeout = 1000 * Timeout;
return request;
}
2.WebClient在异步下载 异步
建立计时器监视响应状况,过时则取消下载 ide
public
class
Calculagraph
{
/// <summary>
/// 时间到事件
/// </summary>
public event TimeoutCaller TimeOver;

/// <summary>
/// 开始时间
/// </summary>
private DateTime _startTime;
private TimeSpan _timeout = new TimeSpan(0, 0, 10);
private bool _hasStarted = false;
object _userdata;

/// <summary>
/// 计时器构造方法
/// </summary>
/// <param name="userdata">计时结束时回调的用户数据</param>
public Calculagraph(object userdata)
{
TimeOver += new TimeoutCaller(OnTimeOver);
_userdata = userdata;
}

/// <summary>
/// 超时退出
/// </summary>
/// <param name="userdata"></param>
public virtual void OnTimeOver(object userdata)
{
Stop();
}

/// <summary>
/// 过时时间(秒)
/// </summary>
public int Timeout
{
get
{
return _timeout.Seconds;
}
set
{
if (value <= 0)
return;
_timeout = new TimeSpan(0, 0, value);
}
}

/// <summary>
/// 是否已经开始计时
/// </summary>
public bool HasStarted
{
get
{
return _hasStarted;
}
}

/// <summary>
/// 开始计时
/// </summary>
public void Start()
{
Reset();
_hasStarted = true;
Thread th = new Thread(WaitCall);
th.IsBackground = true;
th.Start();
}

/// <summary>
/// 重置
/// </summary>
public void Reset()
{
_startTime = DateTime.Now;
}

/// <summary>
/// 中止计时
/// </summary>
public void Stop()
{
_hasStarted = false;
}

/// <summary>
/// 检查是否过时
/// </summary>
/// <returns></returns>
private bool checkTimeout()
{
return (DateTime.Now - _startTime).Seconds >= Timeout;
}

private void WaitCall()
{
try
{
//循环检测是否过时
while (_hasStarted && !checkTimeout())
{
Thread.Sleep(1000);
}
if (TimeOver != null)
TimeOver(_userdata);
}
catch (Exception)
{
Stop();
}
}
}

/// <summary>
/// 过时时回调委托
/// </summary>
/// <param name="userdata"></param>
public
delegate
void
TimeoutCaller(
object
userdata);
public
class
CNNWebClient : WebClient
{

private Calculagraph _timer;
private int _timeOut = 10;

/// <summary>
/// 过时时间
/// </summary>
public int Timeout
{
get
{
return _timeOut;
}
set
{
if (value <= 0)
_timeOut = 10;
_timeOut = value;
}
}

/// <summary>
/// 重写GetWebRequest,添加WebRequest对象超时时间
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
protected override WebRequest GetWebRequest(Uri address)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
request.Timeout = 1000 * Timeout;
request.ReadWriteTimeout = 1000 * Timeout;
return request;
}

/// <summary>
/// 带过时计时的下载
/// </summary>
public void DownloadFileAsyncWithTimeout(Uri address, string fileName, object userToken)
{
if (_timer == null)
{
_timer = new Calculagraph(this);
_timer.Timeout = Timeout;
_timer.TimeOver += new TimeoutCaller(_timer_TimeOver);
this.DownloadProgressChanged += new DownloadProgressChangedEventHandler(CNNWebClient_DownloadProgressChanged);
}

DownloadFileAsync(address, fileName, userToken);
_timer.Start();
}

/// <summary>
/// WebClient下载过程事件,接收到数据时引起
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void CNNWebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
_timer.Reset();//重置计时器
}

/// <summary>
/// 计时器过时
/// </summary>
/// <param name="userdata"></param>
void _timer_TimeOver(object userdata)
{
this.CancelAsync();//取消下载
}
}