c# - GUI task.wait 与控制台或线程池的死锁

标签 c# task

我目前正在深入阅读 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.Currentnull 并且 TaskScheduler.CurrentTaskScheduler.Default,即是,线程池任务调度器。因此,async 方法在线程池线程上恢复并且没有死锁。线程池线程完成async方法,完成Task,让主线程完成等待。

(在死锁情况下,有一个代表 UI 线程的 SynchronizationContext,因此 async 方法尝试在 UI 线程上恢复,但 UI 线程被调用阻塞等待)。

关于c# - GUI task.wait 与控制台或线程池的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19707656/

相关文章:

c# - Json 列 SQL

c# - 写入文件时为 "Cannot access file"

windows - Windows 中的 "Job"(子进程)是什么,何时使用它?

azure - 在Azure环境中最好使用线程或任务库

C# - 当我使用 task::wait() 方法时它抛出异常

c# - 我可以使用计时器每 x 毫秒更新一次标签吗

c# - 装箱 int 不会将其转换为引用类型?

c# - 如何比较两个无序列表框之间的项目

django - 我在使用 Celery、Redis 和 Django 时遇到问题

gradle - 我不知道为什么不执行doFirst()和doLst()