任务的延续(由异步建/等待)是在WPF应用程序主线程运行,但儿童在控制台应用程序 [英] Task's continuation (built by async/await) is running on main thread in a WPF application, but on child in a console application

查看:172
本文介绍了任务的延续(由异步建/等待)是在WPF应用程序主线程运行,但儿童在控制台应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个简单的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆