我在C#中搞乱了async / 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 Console应用程序的异步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”线程。但是我实际上正在努力寻找一些与此相关的明确信息。
答案 0 :(得分:3)
简而言之,如果未设置SynchronizationContext.Current
,则(在控制台应用程序中就是这种情况)。在ThreadPool
上调用等待响应。
在Winforms / WPF上,实现了SynchronizationContext以将对Winforms controlToSendTo.BeginInvoke();
或WPF Dispatcher.BeginInvoke();
的响应排队。
参考:
Await, SynchronizationContext, and Console Apps(开发团队的博客文章by a member):
但是有一种没有
SynchronizationContext
的常见应用程序:控制台应用程序。调用控制台应用程序的Main
方法时,SynchronizationContext.Current
将返回null
。这意味着,如果您在控制台应用程序中调用异步方法,则除非您执行特殊操作,否则您的异步方法将不会具有线程亲和力:这些异步方法中的继续操作可能最终在任何地方运行。
Parallel Computing - It's All About the SynchronizationContext(SynchronizationContext
类的官方文档referenced from文章):
默认情况下,控制台应用程序和Windows服务中的所有线程仅具有默认的
SynchronizationContext
。...
图4
SynchronizationContext
实现的摘要
...╔═════════╦═══════════╦════════════╦════════════╦══════════╦══════════╗ ║ ║ 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 ║ ╚═════════╩═══════════╩════════════╩════════════╩══════════╩══════════╝