ThreadPool.RegisterWaitForSingleObject 设置等待超时事件

来源:互联网 发布:淘宝买家情趣内衣秀 编辑:程序博客网 时间:2024/06/16 18:37

在做文件下载功能时,经常出现网络状况不好而导致文件下载失败的情况,但是这种情况下又不能捕获到异常或者Timeout 回调,如果放之自流,文件将长时间处于下载状态。


基于以上状况引入超时,在网络状态不好的情况下,设置超时时间,例如3秒,然后3秒之后如果没有接收到数据,就断开Socket再重新连接,断点续传。


我们使用

ThreadPool.RegisterWaitForSingleObject

来执行超时设置。

        clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);        //开始连接socket 并且请求Http 头信息,添加TimeOut线程计时,3秒超时;        AutoResetEvent autoResetEvent = new AutoResetEvent(false);        RegisteredWaitHandle waitHandle = ThreadPool.RegisterWaitForSingleObject(autoResetEvent, new WaitOrTimerCallback(TimeOutCallback), null, 3000, true);        clientSocket.Connect(host, 80);        networkStream = new NetworkStream(clientSocket);        var bytes = Encoding.Default.GetBytes(queryStr);        networkStream.Write(bytes, 0, bytes.Length);        waitHandle.Unregister(autoResetEvent);//请求返回,取消超时设置;        var bReader = new BinaryReader(networkStream, Encoding.Default);

    private void TimeOutCallback(object state, bool timeout)    {        Debug.Log("TimeOutCallback");        if (timeout)        {            Debug.LogError("TimeOutCallback  timeout close all");            networkStream.Close();            clientSocket.Close();            m_bDownloadStart = false;        }    }

public static RegisteredWaitHandle RegisterWaitForSingleObject(
     WaitHandle waitObject,
     WaitOrTimerCallback callBack,
     Object state,    
    int millisecondsTimeOutInterval,        //间隔时间
    bool executeOnlyOnce                       //false则循环执行,和Timer类似
)

这个方法的做用是向线程池添加一个可以定时执行的方法,第四个参数millisecondsTimeOutInterval 就是用来设置间隔执行的时间,但是这里第五个参数executeOnlyOnce 会对第四个参数起作用,当它为true时,表示任务仅会执行一次,就是说它不会,像Timer一样,每隔一定时间执行一次,这个功能的话用Timer控件也可以实现

该方法还在此基础上提供了基于信号量来触发执行任务。

信号量也叫开关量,故名思议,它只有两种状态,不是true就是false,

WaitHandle就是这类开关量的基础类,继承它的类有Mutex,ManualResetEvent,AutoResetEvent,一般我们使用后两个

上一点代码

            AutoResetEvent autoResetEvent = new AutoResetEvent(false);            ThreadPool.RegisterWaitForSingleObject(autoResetEvent, new WaitOrTimerCallback((obj, boo) =>            {                Console.Write("obj" + obj);            }), "lll", 3000, false);            //此举很重要,因为ThreadPool是Background的的,所以要等待着,否则就执行完了            Console.Read();


每隔3秒输出 "objlll"




0 0