Search code examples
c#timeoutthreadpoolsynchronousbegininvoke

Better time-out detection for synchronous operations


I need a way to perform some action synchronously which should complete in half a second, but might just hang around for minutes. If it times out I don't care about the result. Here's the I'm doing it right now using compiler-generated delegate.BeginInvoke:

static void Main()
{
    bool disposed = false;
    var wait = new ManualResetEvent(false);
    var a = new Action(
        () =>
            {
                Thread.Sleep(1000); // <- some looong action

                if (!disposed)
                    lock (wait)
                        if (!disposed)
                            wait.Set();
            });

    a.BeginInvoke(a.EndInvoke, null);

    bool success = wait.WaitOne(500);
    Console.WriteLine(success ? "success" : "timeout");

    lock (wait)
    {
        wait.Dispose();
        disposed = true;
    }

    Console.ReadLine();
}

Looks ugly. And I'm aware lambda closure's disposed variable is modified (unlike my ReSharper, I like this C# feature). All because I want to dispose ManualResetEvent. Can you suggest better approach in .NET4? Perhaps should I just skip disposing the event and rely on GC?

One note: ManualResetEvent.Set() explodes if you try to do it on disposed instance.


Solution

  • Ugh, now that I looked a bit more at code samples using compiler-generated delegate.BeginInvoke I see that it returns IAsyncResult which has AsyncWaitHandle exactly for my goal:

    var a = new Action(() => Thread.Sleep(1000)); // <- some looong action
    IAsyncResult asyncResult = a.BeginInvoke(a.EndInvoke, null);
    bool success = asyncResult.AsyncWaitHandle.WaitOne(500);
    

    That wait handle in case of AsyncResult is in fact an instance of ManualResetEvent which is disposed automatically from thread-pool thread right when my asynchronous call completes.