[转载]WebClient的超时问题及解决

Webclient在下载请求时无法设置请求超时时间和请求读写超时时间。WebClient在异步下载时遇到网络不通等问题时没有响应超时造成app挂起。

1.Webclient请求超时设置
      重写Webclient的GetWebRequest方法,为HttpWebRequest添加请求超时及读写超时

      

        protected override WebRequest GetWebRequest(Uri address)
        
{
            HttpWebRequest request 
= (HttpWebRequest)base.GetWebRequest(address);
            request.Timeout 
= 1000 * Timeout;
            request.ReadWriteTimeout 
= 1000 * Timeout;
            
return request;
        }

 

2.WebClient在异步下载

       创建计时器监视响应情况,过期则取消下载

      

    public class Calculagraph
    
{
        
/// <summary>
        
/// 时间到事件
        
/// </summary>

        public event TimeoutCaller TimeOver;

        
/// <summary>
        
/// 开始时间
        
/// </summary>

        private DateTime _startTime;
        
private TimeSpan _timeout = new TimeSpan(0010);
        
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(00, 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();//取消下载
        }

    }

 

 

posted @ 2010-10-15 17:58  陈 锋  阅读(2783)  评论(0编辑  收藏  举报