C#中,函数运行超时的功能的实现

主要使用BeginInvoke方法和ManualResetEvent类来实现。

成都创新互联是一家集网站建设,安达企业网站建设,安达品牌网站建设,网站定制,安达网站建设报价,网络营销,网络优化,安达网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。

BeginInvoke使得函数在线程池上异步运行,运行完成后,调用回调函数。

ManualResetEvent用于同步阻塞。

设计思想如下:

当函数在线程池中的某一线程上异步的运行的时候,ManualResetEvent阻塞当前线程,等待若干时间。

在等候期间,如果异步函数运行完毕,会对ManualResetEvent设置一个信号,使得阻塞的线程得以继续运行下去。

如果等候超时了,则阻塞的线程也会取消阻塞,继续运行下去,但是不再理会回调的函数。(即使回调函数仍然被调用),事实上,BeginInvoke创建的线程都是后台线程,这种线程一但所有的前台线程都退出后(其中主线程就是一个前台线程),不管后台线程是否执行完毕,都会结束线程,并退出。因此如果阻塞的主线程完全运行完毕退出,那么异步运行的线程也会退出,无论是否运行完毕。

语句isGetSignal = manu.WaitOne(timeout);就是阻塞当前线程一段时间。

该语句阻塞期间,不会对isGetSignal赋值,直到阻塞取消后,才会返回一个值给isGetSignal。

当阻塞是因为收到信号而取消的,得到的值是true。

当阻塞是因为超时而取消的,得到的值是false。

整个流程如下:

C#中,函数运行超时的功能的实现

把这些代码逻辑封装成一个类。

这个类就接受一个委托和一个超时时间作为构造函数。

把这个委托和 ManualResetEvent .Set();语句写在一个方法体内,CombineActionAndManuset,因此CombineActionAndManuset的调用就是实现了方法运行完毕后,设置取消阻塞信号。

封装后的代码:

  1. public class FuncTimeout  
  2.    {  
  3.        ///  
  4.        /// 信号量 
  5.        ///  
  6.        public ManualResetEvent manu = new ManualResetEvent(false);  
  7.        ///  
  8.        /// 是否接受到信号 
  9.        ///  
  10.  
  11.        public bool isGetSignal;  
  12.        ///  
  13.        /// 设置超时时间 
  14.        ///  
  15.        public int timeout;  
  16.        ///  
  17.        /// 要调用的方法的一个委托 
  18.        ///  
  19.        public Action FunctionNeedRun;  
  20.  
  21.        ///  
  22.        /// 构造函数,传入超时的时间以及运行的方法 
  23.        ///  
  24.        ///  
  25.        ///  
  26.        public FuncTimeout(Action _action, int _timeout)  
  27.        {  
  28.            FunctionNeedRun = _action;  
  29.            timeout = _timeout;  
  30.        }  
  31.  
  32.        ///  
  33.        /// 回调函数 
  34.        ///  
  35.        ///  
  36.        public void MyAsyncCallback(IAsyncResult ar)  
  37.        {  
  38.            //isGetSignal为false,表示异步方法其实已经超出设置的时间,此时不再需要执行回调方法。 
  39.            if (isGetSignal == false)  
  40.            {  
  41.                Console.WriteLine("放弃执行回调函数");  
  42.                Thread.CurrentThread.Abort();  
  43.            }  
  44.            else 
  45.            {  
  46.                Console.WriteLine("调用回调函数");  
  47.            }  
  48.        }  
  49.  
  50.        ///  
  51.        /// 调用函数 
  52.        ///  
  53.        ///  
  54.        public void doAction(int param1)  
  55.        {  
  56.            Action WhatTodo = CombineActionAndManuset;  
  57.            //通过BeginInvoke方法,在线程池上异步的执行方法。 
  58.            var r=WhatTodo.BeginInvoke(param1, MyAsyncCallback, null);  
  59.            //设置阻塞,如果上述的BeginInvoke方法在timeout之前运行完毕,则manu会收到信号。此时isGetSignal为true。 
  60.            //如果timeout时间内,还未收到信号,即异步方法还未运行完毕,则isGetSignal为false。 
  61.            isGetSignal = manu.WaitOne(timeout);  
  62.              
  63.            if (isGetSignal == true)  
  64.            {  
  65.                Console.WriteLine("函数运行完毕,收到设置信号,异步执行未超时");  
  66.            }  
  67.            else 
  68.            {  
  69.                Console.WriteLine("没有收到设置信号,异步执行超时");  
  70.            }  
  71.        }  
  72.  
  73.        ///  
  74.        /// 把要传进来的方法,和 manu.Set()的方法合并到一个方法体。 
  75.        /// action方法运行完毕后,设置信号量,以取消阻塞。 
  76.        ///  
  77.        ///  
  78.        public void CombineActionAndManuset(int num)  
  79.        {  
  80.            FunctionNeedRun(num);  
  81.            manu.Set();  
  82.        }  
  83.    }  

测试代码:

 

  1. class Program  
  2.     {  
  3.         static void Main(string[] args)  
  4.         {  
  5.             FuncTimeout ft = new FuncTimeout(dosth, 3000);  
  6.             ft.doAction(6);  
  7.         }  
  8.  
  9.        static void dosth(int num)  
  10.         {  
  11.             for (int i = 0; i < num; i++)  
  12.             {  
  13.                 Thread.Sleep(500);  
  14.                 Console.Write(i);  
  15.             }  
  16.         }  
  17.     } 

 

当超时时间设置为5s的时候,方法未超时

C#中,函数运行超时的功能的实现

当超时时间设置为1s的时候,方法超时

C#中,函数运行超时的功能的实现

附件:http://down.51cto.com/data/2361797

分享标题:C#中,函数运行超时的功能的实现
网址分享:http://pwwzsj.com/article/psdigo.html