Search code examples
c#task-parallel-libraryrace-condition

Task::ConfigureAwait - a race condition?


Imagine a sitution when caller creates a task:

{
 var tWithCapturedCtx = Task.Run(...);
 var tWithoutCapturedCtx = tWithCapturedCtx.ConfigureAwait(false);

 await tWithoutCapturedCtx;
}

Is there a possibility that tWithCapturedCtx will execute so fast that the continuation will be executed on the captured context?


Solution

  • Is there a possibility that tWithCapturedCtx will execute so fast that the continuation will be executed on the captured context?

    Sort of.

    If tWithCapturedCtx is already finished by the time the await is evaluated (which means tWithoutCapturedCtx is also already finished), then there is no continuation at all. The async method just continues executing synchronously (on the same context).

    However, if tWithCapturedCtx is not already finished by the time the await is evaluated (which means tWithoutCapturedCtx is also not already finished), then the continuation is scheduled without the context being captured.

    There's another, even smaller, race condition between when the await checks if its awaitable is complete and when await schedules the continuation. If the awaitable completes within that window, then the continuation is just run synchronously (again, on the same context).

    In conclusion, ConfigureAwait(false) means "I don't care what context the rest of this method runs in"; it does not mean "run the rest of this method on the thread pool". If you want to say "run this other code on a thread pool thread", then use Task.Run.