0

I have a problem. An exception in the ThreadPool.QueueUserWorkItem does not crash an application, but I want it to crash it and I know normally it does. There is a difference in my case. My ThreadPool.QueueUserWorkItem is wrapped up into an awaiter like this

public struct YieldThreadPoolAwaiter : INotifyCompletion
{
    public void OnCompleted(Action continuation)
    {
        if (continuation == null)
        {
            throw new ArgumentNullException(nameof(continuation));
        }
        ThreadPool.QueueUserWorkItem(RunAction, continuation);
    }

    public void GetResult() { }

    private static void RunAction(object state)
    {
        ((Action)state)();
    }

    public bool IsCompleted
    {
        get { return false; }
    }
}

To me, it looks the same as just calling ThreadPool.QueueUserWorkItem but here it is called indirectly when I do:

await ThreadPoolEx.Yield();

I see that the execution goes inside ThreadPool.QueueUserWorkItem, I know an exception is thrown there but the exception is somehow quietly swallowed, and the application does not crash.

The question is - WHY? What special .NET Framework is doing that the application does not crash in this case and how to change back this behavior and make it crash?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Alex
  • 655
  • 1
  • 8
  • 16

1 Answers1

1

I suspect that you are calling await ThreadPoolEx.Yield(); from within an async Task method, like this fiddle.

In that case, the continuation passed to OnCompleted is not just your code; it's the appropriate part of the code generated by the async state machine. And if that code is in an async Task method, then part of that generated state machine code deliberately catches exceptions and places them on the returned task.

To summarize: behavior is as expected. If you want an exception within an async method to crash the app, use async void instead of async Task.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810