C#函數運行超時則終止執行(任意參數類型及參數個數通用版)


現在有更方便的實現方式:
static void Main(string[] args)
{

    string input = " ";

    Task.Factory.StartNew(() => { input = Console.ReadLine(); }).Wait(10 * 1000);

    Console.WriteLine(input);
}

  

以下是原來的實現方式:
/// <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;
    }
}

  

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM