任务的延续(由异步建/等待)是在WPF应用程序主线程运行,但儿童在控制台应用程序 [英] Task's continuation (built by async/await) is running on main thread in a WPF application, but on child in a console application
问题描述
假设我有一个简单的 C#
控制台应用程序:
Assume I have a simple C#
Console Application:
class Program
{
static async void func()
{
Thread.CurrentThread.Name = "main";
await Task.Run(() =>
{
Thread.CurrentThread.Name = "child";
Thread.Sleep(5000);
});
Console.WriteLine("continuation is running on {0} thread", Thread.CurrentThread.Name);
}
static void Main(string[] args)
{
func();
Thread.Sleep(10000);
}
}
在5000毫秒传递,我们看到消息的延续是在子线程运行。当另一个5000毫秒传球,主线程完成其工作并关闭应用程序。它看起来相当的逻辑:异步任务及其延续在同一子线程上运行
When 5000 ms pass, we see the "continuation is running on child thread" message. When another 5000 ms pass, main thread finishes its work and application is closed. It looks rather logical: asynchronous task and its continuation are running on the same child thread.
但现在假设我有一个简单的 WPF
应用程序:
But assume now I have a simple WPF
application:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
async private void mainWnd_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Thread.CurrentThread.Name = "main";
await Task.Run(() =>
{
Thread.CurrentThread.Name = "child";
Thread.Sleep(5000);
});
this.Title = string.Format("continuation is running on {0} thread", Thread.CurrentThread.Name);
}
private void mainWnd_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
Thread.Sleep(10000);
}
}
现在,当我们preSS鼠标左键和5000毫秒传递,我们看到标题的延续是在主线程中运行。此外,如果我们preSS左键,然后鼠标右键,应用程序第一次运行 mainWnd_MouseLeftButtonDown
处理程序,那么 mainWnd_MouseRightButtonDown
处理程序(在主线程),主线程会睡眠10000毫秒,然后异步任务从 mainWnd_MouseLeftButtonDown
延续将在主线程上执行。
Now when we press left mouse button and 5000 ms pass, we see "continuation is running on main thread" title. Moreover, if we press left button and then right button, application first will run mainWnd_MouseLeftButtonDown
handler, then mainWnd_MouseRightButtonDown
handler (on main thread), main thread will sleep for 10000 ms, and then continuation of asynchronous task from mainWnd_MouseLeftButtonDown
will be still performed on main thread.
为什么异步的await
机制,这两种情况有什么不同?
Why does async-await
mechanism differ for these two situations?
我知道,在 WPF
方法可以明确地在UI线程通过 Dispatcher.Invoke
运行,但异步的await
机制尚不 WPF
特异性,所以它的行为应该是任何类型的应用程序平等的,不应该呢?
I know that in WPF
method can be explicitly run on UI thread through Dispatcher.Invoke
, but async-await
mechanism isn't WPF
-specific, so its behavior should be equal in any kind of application, shouldn't it?
任何帮助将AP preciated。
Any help will be appreciated.
推荐答案
异步等待
尊重当前范围的的 的SynchronizationContext
。这意味着,当异步操作开始与结束的延续定于所捕获的上下文的上下文(如果存在)被捕获。
async-await
respects the current scope's SynchronizationContext
. That means that the context (if it exists) is captured when the asynchronous operation starts and when it ends the continuation is scheduled on the captured context.
UI
应用程序( WPF
/ 的WinForms
)的使用一个的SynchronizationContext
,只允许在主( UI
)线程与 UI <互动/ code>元素,所以它无缝地与
和异步等待
。
UI
applications (WPF
/Winforms
) use a SynchronizationContext
that allows only for the main (UI
) thread to interact with the UI
elements, so it seamlessly works with async-await
.
ASP.Net
也有它自己的的SynchronizationContext
所谓的 AspNetSynchronizationContext
(奇怪)。所以它不一定是关于 UI
或单线程公寓。
ASP.Net
also has it's own SynchronizationContext
called AspNetSynchronizationContext
(surprisingly). So it isn't necessarily about UI
or Single Thread Apartments.
如果您希望禁用有用的SynchronizationContext
捕捉你只需要使用<一个href=\"http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.configureawait%28v=vs.110%29.aspx\"相对=nofollow> ConfigureAwait
:
If you want to disable that useful SynchronizationContext
capturing you just need to use ConfigureAwait
:
await Task.Run(() =>
{
Thread.CurrentThread.Name = "child";
Thread.Sleep(5000);
}).ConfigureAwait(false);
更多关于SynchronizationContexts:这是所有关于SynchronizationContext的
这篇关于任务的延续(由异步建/等待)是在WPF应用程序主线程运行,但儿童在控制台应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!