狀況
.NET Framework 的 4.6 加入新列舉型別值, RunContinuationsAsynchronously, TaskCompletionSource和TaskCreationOptions的列舉。這個值會強制以非同步方式執行的工作,這有助於避免死結情況。然而,會發現問題,針對某些特定類型的接續符號 (尤其當Task.WhenAll、 Task.WhenAny或TaskExtensions.Unwrap建立接續符號) 中,會忽略這個選項。因此,接續符號可能仍會同步執行。
下列範例會顯示問題。如果能正確運作的RunContinuationsAsynchronously值,兩個執行緒會列印出的識別碼不會相同,因為接續一定會排程到不同的執行緒。
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 小組正在使用的解決方案包含在未來的更新。