gpt4 book ai didi

c# - 任务的延续(由 async/await 构建)在 WPF 应用程序的主线程上运行,但在控制台应用程序的子线程上运行

转载 作者:太空宇宙 更新时间:2023-11-03 17:51:36 25 4
gpt4 key购买 nike

假设我有一个简单的 C# 控制台应用程序:

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 毫秒过去时,我们看到“continuation is running on child thread”消息。当另一个 5000 毫秒过去时,主线程完成其工作并关闭应用程序。它看起来很合乎逻辑:异步任务及其延续运行在同一个子线程上。

但假设现在我有一个简单的 WPF 应用程序:

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);
}
}

现在,当我们按下鼠标左键并经过 5000 毫秒时,我们会看到“continuation is running on main thread”标题。此外,如果我们按左键然后按右键,应用程序将首先运行 mainWnd_MouseLeftButtonDown 处理程序,然后是 mainWnd_MouseRightButtonDown 处理程序(在主线程上),主线程将休眠 10000 毫秒,然后来自 mainWnd_MouseLeftButtonDown 的异步任务的继续将仍然在主线程上执行。

为什么 async-await 机制在这两种情况下不同?

我知道在 WPF 中,方法可以通过 Dispatcher.Invoke 在 UI 线程上显式运行,但是 async-await 机制不是WPF-specific,所以它的行为在任何类型的应用程序中都应该是相同的,不是吗?

我们将不胜感激。

最佳答案

async-await 尊重当前范围的 SynchronizationContext .这意味着上下文(如果存在)在异步操作开始时被捕获,而在异步操作结束时,将在捕获的上下文上安排延续。

UI 应用程序 (WPF/Winforms) 使用 SynchronizationContext 只允许主要 (UI) 线程与 UI 元素交互,因此它与 async-await 无缝协作。

ASP.Net 也有它自己的 SynchronizationContext 称为 AspNetSynchronizationContext (出奇)。所以它不一定与 UISingle Thread Apartments 有关.


如果你想禁用有用的 SynchronizationContext 捕获,你只需要使用 ConfigureAwait :

await Task.Run(() =>
{
Thread.CurrentThread.Name = "child";
Thread.Sleep(5000);
}).ConfigureAwait(false);

有关 SynchronizationContext 的更多信息:It's All About the SynchronizationContext

关于c# - 任务的延续(由 async/await 构建)在 WPF 应用程序的主线程上运行,但在控制台应用程序的子线程上运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24072643/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com