猿问

异步.NET控制台程序中的线程控制流

我在 C# 中弄乱了 async/await 只是为了深入研究一些线程控制流并偶然发现了一个不寻常的行为,我真的很感谢澄清。即使 Task 本身在后台执行,await 之后的执行也会在调用线程上继续执行,这是有道理的。事实上,这正是发生在 WPF 中的情况。

以下代码:


private async void Button_Click(object sender, RoutedEventArgs e)

{

    Console.WriteLine($"Start. Thread: {Thread.CurrentThread.ManagedThreadId}");

    await Task.Run(async () => await Task.Delay(1000));

    Console.WriteLine($"End. Thread: {Thread.CurrentThread.ManagedThreadId}");

}

结果:

开始。线程:1

结束。线程:1


我意识到这是使程序流可预测等的方法。


但令我惊讶的是 .NET 控制台应用程序的异步 Main 方法功能显示出有些不同的行为。

相同的代码:


static async Task Main(string[] args)

{

    Console.WriteLine($"Start. Thread: {Thread.CurrentThread.ManagedThreadId}");

    await Task.Run(async () => await Task.Delay(1000));

    Console.WriteLine($"End. Thread: {Thread.CurrentThread.ManagedThreadId}");

}

导致不同的线程控制流程:

启动。线程:1

结束。线程:5


我的猜测是,控制台应用程序具有不同的同步上下文概念,并且不像 WPF 那样绑定到主“UI”线程。但我实际上正在努力寻找一些明确的信息。


慕仙森
浏览 76回答 1
1回答

千巷猫影

简而言之,当SynchronizationContext.Current未设置时,(控制台应用程序就是这种情况)。在 上调用 await 响应ThreadPool。controlToSendTo.BeginInvoke();在 Winforms/WPF 上,实现了 SynchronizationContext 以将对 winforms或 WPF的响应排队Dispatcher.BeginInvoke();。参考:Await、SynchronizationContext 和控制台应用程序(开发团队成员的博客文章):但是有一种常见的应用程序没有SynchronizationContext:控制台应用程序。当您的控制台应用程序的Main方法被调用时,SynchronizationContext.Current将返回null. 这意味着如果您在控制台应用程序中调用一个异步方法,除非您做一些特殊的事情,否则您的异步方法将没有线程亲和力:这些异步方法中的延续最终可能会“在任何地方”运行。Parallel Computing - It's All About the SynchronizationContext(这篇文章引用自该类的官方文档SynchronizationContext):默认情况下,控制台应用程序和 Windows 服务中的所有线程都只有默认的SynchronizationContext....图 4SynchronizationContext实施摘要...╔═════════╦═══════════╦════════════╦════════════╦══════════╦══════════╗║         ║ Specific  ║ Exclusive  ║ Ordered    ║ Send May ║ Post May ║║         ║ Thread    ║ (Delegates ║ (Delegates ║ Invoke   ║ Invoke   ║║         ║ Used to   ║ Execute    ║ Execute    ║ Delegate ║ Delegate ║║         ║ Execute   ║ One at     ║ in Queue   ║ Directly ║ Directly ║║         ║ Delegates ║ a Time)    ║ Order)     ║          ║          ║╠═════════╬═══════════╬════════════╬════════════╬══════════╬══════════╣║ ...     ║           ║            ║            ║          ║          ║╠═════════╬═══════════╬════════════╬════════════╬══════════╬══════════╣║ Default ║ No        ║ No         ║ No         ║ Always   ║ Never    ║╚═════════╩═══════════╩════════════╩════════════╩══════════╩══════════╝
随时随地看视频慕课网APP
我要回答