• 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();//取消下载
            }

        }
  • 相关阅读:
    上篇用到的matcher函数
    lambdaj学习
    Redis高级应用——2
    Redis入门
    从gitee 下载代码到本地
    CSS中对图片(background)的一些设置心得总结
    nodejs 安装Ionic 和cordova
    Spring MVC内容协商机制详解
    基于Servlet3.0的编程式SpringMVC实例详解
    基于Junit的Spring集成测试方法
  • 原文地址:https://www.cnblogs.com/heros/p/1517997.html
Copyright © 2020-2023  润新知