/// <summary> /// 控制函數執行時間,超時返回null不繼續執行 /// 調用方法 /// FuncTimeout.EventNeedRun action = delegate(object[] param) /// { /// //調用自定義函數 /// return Test(param[0].ToString(), param[1].ToString(), (DateTime)param[2]); /// }; /// FuncTimeout ft = new FuncTimeout(action, 2000); /// var result = ft.doAction("1", "2", DateTime.Now); /// </summary> public class FuncTimeout { /// <summary> /// 信號量 /// </summary> public ManualResetEvent manu = new ManualResetEvent(false); /// <summary> /// 是否接受到信號 /// </summary> public bool isGetSignal; /// <summary> /// 設置超時時間 /// </summary> public int timeout; /// <summary> /// 定義一個委托 ,輸入參數可選,輸出object /// </summary> public delegate object EventNeedRun(params object[] param); /// <summary> /// 要調用的方法的一個委托 /// </summary> private EventNeedRun FunctionNeedRun; /// <summary> /// 構造函數,傳入超時的時間以及運行的方法 /// </summary> /// <param name="_action">運行的方法 </param> /// <param name="_timeout">超時的時間</param> public FuncTimeout(EventNeedRun _action, int _timeout) { FunctionNeedRun = _action; timeout = _timeout; } /// <summary> /// 回調函數 /// </summary> /// <param name="ar"></param> public void MyAsyncCallback(IAsyncResult ar) { //isGetSignal為false,表示異步方法其實已經超出設置的時間,此時不再需要執行回調方法。 if (isGetSignal == false) { //放棄執行回調函數; Thread.CurrentThread.Abort(); } } /// <summary> /// 調用函數 /// </summary> /// <param name="input">可選個數的輸入參數</param> /// <returns></returns> public object doAction(params object[] input) { EventNeedRun WhatTodo = CombineActionAndManuset; //通過BeginInvoke方法,在線程池上異步的執行方法。 var r = WhatTodo.BeginInvoke(input, MyAsyncCallback, null); //設置阻塞,如果上述的BeginInvoke方法在timeout之前運行完畢,則manu會收到信號。此時isGetSignal為true。 //如果timeout時間內,還未收到信號,即異步方法還未運行完畢,則isGetSignal為false。 isGetSignal = manu.WaitOne(timeout); if (isGetSignal == true) { return WhatTodo.EndInvoke(r); } else { return null; } } /// <summary> /// 把要傳進來的方法,和 manu.Set()的方法合並到一個方法體。 /// action方法運行完畢後,設置信號量,以取消阻塞。 /// </summary> /// <param name="input">輸入參數</param> /// <returns></returns> public object CombineActionAndManuset(params object[] input) { var output = FunctionNeedRun(input); manu.Set(); return output; } }