The .NET Framework 4.6 added a new enum type value, RunContinuationsAsynchronously, to the TaskCompletionSource and TaskCreationOptions enums. This value forces tasks to run asynchronously, and this helps to avoid deadlock situations. However, an issue has been discovered where, for some specific kinds of continuations (in particular when Task.WhenAll, Task.WhenAny, or TaskExtensions.Unwrap create the continuations), the option is ignored. Therefore, continuations may still run synchronously.
The following sample shows the problem. If the RunContinuationsAsynchronously value were functioning correctly, the two thread IDs that are printed out would never be the same, because the continuation would always be scheduled onto different threads.
The following sample shows the problem. If the RunContinuationsAsynchronously value were functioning correctly, the two thread IDs that are printed out would never be the same, because the continuation would always be scheduled onto different threads.
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
var mres = new ManualResetEventSlim();
Console.WriteLine(Environment.CurrentManagedThreadId);
var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
var t = Task.WhenAll(tcs.Task);
t.ContinueWith(delegate
{
Console.WriteLine(Environment.CurrentManagedThreadId);
mres.Set();
}, TaskContinuationOptions.ExecuteSynchronously);
tcs.SetResult(true);
mres.Wait();
}
}