gpt4 book ai didi

c# - 为什么await Task.Run() 不同步回UI 线程/原始上下文?

转载 作者:行者123 更新时间:2023-12-02 00:04:59 24 4
gpt4 key购买 nike

我以为我理解了异步等待模式Task.Run操作。
但我想知道为什么在下面的代码示例中,从完成的任务返回后,await 没有同步回 UI 线程。

public async Task InitializeAsync()
{
Console.WriteLine($"Thread: {Thread.CurrentThread.ManagedThreadId}"); // "Thread: 1"
double value = await Task.Run(() =>
{
Console.WriteLine($"Thread: {Thread.CurrentThread.ManagedThreadId}"); // Thread: 6

// Do some CPU expensive stuff
double x = 42;
for (int i = 0; i < 100000000; i++)
{
x += i - Math.PI;
}
return x;
}).ConfigureAwait(true);
Console.WriteLine($"Result: {value}");
Console.WriteLine($"Thread: {Thread.CurrentThread.ManagedThreadId}"); // Thread: 6 - WHY??
}

此代码在附带 Visual Studio 2019 调试器的 Windows 10 系统上的 .NET Framework WPF 应用程序中运行。
我从我的 App 类的构造函数中调用此代码。

public App()
{
this.InitializeAsync().ConfigureAwait(true);
}

也许这不是最好的方法,但我不确定这是否是奇怪行为的原因。

代码从 UI 线程开始,应该执行一些任务。通过 await 操作和 ConfigureAwait(true) 任务完成后,它应该在主线程 (1) 上继续。但事实并非如此。

为什么?

最佳答案

这是一件棘手的事情。

您正在 UI 线程上调用 await,这是真的。但!您正在 App 的构造函数内执行此操作。

请记住,隐式生成的启动代码如下所示:

public static void Main()
{
var app = new YourNamespace.App();
app.InitializeComponent();
app.Run();
}

事件循环用于返回主线程,仅作为 Run 执行的一部分启动。因此,在 App 构造函数运行期间,没有事件循环。然而。

因此,技术上负责在 await 之后将流程返回到主线程的 SynchronizationContextnull应用程序的构造函数。

(SynchronizationContextawait 在等待之前 捕获,因此完成 之后 并不重要Task 已经有一个有效的 SynchronizationContext:捕获的值为 null,因此 await 继续在线程池上执行线程。)

所以问题不在于您在构造函数中运行代码,问题在于您在 App 的构造函数中运行代码,此时应用程序尚未完全设置等待执行。 MainWindow 构造函数中的相同代码表现良好。

让我们做一些实验:

public App()
{
Console.WriteLine($"sc = {SynchronizationContext.Current?.ToString() ?? "null"}");
}

protected override void OnStartup(StartupEventArgs e)
{
Console.WriteLine($"sc = {SynchronizationContext.Current?.ToString() ?? "null"}");
base.OnStartup(e);
}

第一个输出给出

sc = null

第二个

sc = System.Windows.Threading.DispatcherSynchronizationContext

因此您可以看到 OnStartup 中已经存在同步上下文。因此,如果您将 InitializeAsync() 移至 OnStartup,它将按照您的预期运行。

关于c# - 为什么await Task.Run() 不同步回UI 线程/原始上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59225570/

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