我目前正在深入阅读 C#(第 3 版),给出的警告之一是将 GUI 线程与 task.wait 一起使用是危险的,因为它可能会导致死锁。但它不是 ThreadPool 或 Console 的问题。我的问题是为什么运行 task.wait 的线程不会死锁,所以对于以下代码(摘自书中),即使是控制台应用程序(后台)线程也不会进入捕获状态,因为它会死锁。
public static void Main(string[] args = null)
{
var source = new CancellationTokenSource();
var task = TestInt(source.Token);
source.CancelAfter(4000);
Console.WriteLine("Status {0}",task.Status);
try
{
task.Wait();
}
catch (AggregateException e)
{
Console.WriteLine("Caught {0}",e.InnerExceptions[0]);
}
Console.WriteLine("Final Status: {0}",task.Status);
Console.ReadKey();
}
public static async Task TestInt(CancellationToken token, double start = 1)
{
await Task.Delay(TimeSpan.FromSeconds(30), token);
}
谢谢你
最佳答案
我详细解释一下in a blog post .
发生的事情是(默认情况下)await
将捕获当前“上下文”并使用该上下文来恢复执行 async
方法。这个“上下文”是 SynchronizationContext.Current
除非它是 null
,在这种情况下它是 TaskScheduler.Current
。
在您的示例中,SynchronizationContext.Current
是 null
并且 TaskScheduler.Current
是 TaskScheduler.Default
,即是,线程池任务调度器。因此,async
方法在线程池线程上恢复并且没有死锁。线程池线程完成async
方法,完成Task
,让主线程完成等待。
(在死锁情况下,有一个代表 UI 线程的 SynchronizationContext
,因此 async
方法尝试在 UI 线程上恢复,但 UI 线程被调用阻塞等待
)。
关于c# - GUI task.wait 与控制台或线程池的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19707656/