我在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控制台应用程序的异步主方法功能显示了一些不同的行为。 相同的代码:
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”线程。但我实际上正在努力找到一些明确的信息。
简而言之,当没有设置SynchronizationContext.Current
时(控制台应用程序就是这种情况)。在ThreadPool
上调用await响应。
在Winforms / WPF上,实现SynchronizationContext以将响应排入winforms controlToSendTo.BeginInvoke();
或WPF Dispatcher.BeginInvoke();
。
参考:
SynchronizationContext
:控制台应用程序。当您的控制台应用程序的Main
方法被调用时,SynchronizationContext.Current
将返回null
。这意味着如果您在控制台应用程序中调用异步方法,除非您执行某些特殊操作,否则您的异步方法将不具有线程关联性:这些异步方法中的延续可能最终“在任何地方”运行。SynchronizationContext
类的官方文档):
默认情况下,控制台应用程序和Windows服务中的所有线程仅具有默认的SynchronizationContext
。
...
图4 SynchronizationContext
实现的摘要
...
╔═════════╦═══════════╦════════════╦════════════╦═ ═══════════════════╗║║║║║║║║║║║║║║║May MayMay║║║║║║║║║║║║Deleg║║║║║║║║║║Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg Deleg DelegDeleg║Deleg Deleg Deleg Deleg Deleg Deleg Deleg DelegDeleg║║║║║║║║║║║║║║║║║║║║║║║║║║║║║║║║║║║║║║║ ║用于║执行║执行║代表║代表║║║执行║一个在队列中的║直接║直接║║║代表║a时间║命令)║║║╠══════════╬ ═══════════╬════════════╬════════════╬══════════╬═ ══════════╣║║║║║║║══════════════════════════════════════════════════════════════════════════════ ═════╬════════════╬══════════╬═══════ ══╣╣默认║否║否║否║始终║从不║║════════════════════════════════════════════════════════════════════════════════════ ═╩════════════╩══════════╩══════════╝