症状
.NET Framework 4.6 添加新的枚举类型值, RunContinuationsAsynchronously, TaskCompletionSource和TaskCreationOptions枚举。该值将强制任务异步运行,这有助于避免死锁情况。然而,一个问题已经被发现,对于延续 ( Task.WhenAll、 Task.WhenAny或TaskExtensions.Unwrap在创建延续任务时尤其) 是在某些特定类型,将忽略此选项。因此,延续可能仍以同步方式运行。
下面的示例显示了此问题。如果RunContinuationsAsynchronously的值正常的两个线程打印出来的 Id 将永远不会变,因为总是会到不同的线程上安排延续。
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();
}
}
解决方案
目前尚无解决此问题的方法。Microsoft.NET Framework 工作组在将来的更新中包括的解决方案。