zoukankan      html  css  js  c++  java
  • 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();//取消下载
            }

        }
  • 相关阅读:
    《Java TCP/IP Socket 编程 》读书笔记之十一:深入剖析socket——TCP套接字的生命周期
    c++实现二分查找
    hadoop序列化机制与java序列化机制对比
    C、C++中“*”操作符和“后++”操作符的优先级
    poj2774之最长公共子串
    Python之美[从菜鸟到高手]--urlparse源码分析
    (程序员面试题)字符串处理之寻找最大不重复子串
    hdu 4782 Beautiful Soupz
    教程Xcode 下编译发布与提交App到AppStore
    云端的ABAP Restful服务开发
  • 原文地址:https://www.cnblogs.com/heros/p/1517997.html
Copyright © 2011-2022 走看看