Implement C# Generic Timeout

后端 未结 7 1733
谎友^
谎友^ 2020-11-22 09:39

I am looking for good ideas for implementing a generic way to have a single line (or anonymous delegate) of code execute with a timeout.

TemperamentalClass t         


        
7条回答
  •  遇见更好的自我
    2020-11-22 10:23

    Some minor changes to Pop Catalin's great answer:

    • Func instead of Action
    • Throw exception on bad timeout value
    • Calling EndInvoke in case of timeout

    Overloads have been added to support signaling worker to cancel execution:

    public static T Invoke (Func function, TimeSpan timeout) {
        if (timeout.TotalMilliseconds <= 0)
            throw new ArgumentOutOfRangeException ("timeout");
    
        CancelEventArgs args = new CancelEventArgs (false);
        IAsyncResult functionResult = function.BeginInvoke (args, null, null);
        WaitHandle waitHandle = functionResult.AsyncWaitHandle;
        if (!waitHandle.WaitOne (timeout)) {
            args.Cancel = true; // flag to worker that it should cancel!
            /* •————————————————————————————————————————————————————————————————————————•
               | IMPORTANT: Always call EndInvoke to complete your asynchronous call.   |
               | http://msdn.microsoft.com/en-us/library/2e08f6yc(VS.80).aspx           |
               | (even though we arn't interested in the result)                        |
               •————————————————————————————————————————————————————————————————————————• */
            ThreadPool.UnsafeRegisterWaitForSingleObject (waitHandle,
                (state, timedOut) => function.EndInvoke (functionResult),
                null, -1, true);
            throw new TimeoutException ();
        }
        else
            return function.EndInvoke (functionResult);
    }
    
    public static T Invoke (Func function, TimeSpan timeout) {
        return Invoke (args => function (), timeout); // ignore CancelEventArgs
    }
    
    public static void Invoke (Action action, TimeSpan timeout) {
        Invoke (args => { // pass a function that returns 0 & ignore result
            action (args);
            return 0;
        }, timeout);
    }
    
    public static void TryInvoke (Action action, TimeSpan timeout) {
        Invoke (args => action (), timeout); // ignore CancelEventArgs
    }
    

提交回复
热议问题