gpt4 book ai didi

c# - await Task 与 await Task.Run(voidMethod)

转载 作者:太空宇宙 更新时间:2023-11-03 18:27:37 24 4
gpt4 key购买 nike

我很困惑为什么这两个程序的输出不同:

private async void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 33; i++)
{
await LongProcess();
}
}

private async Task LongProcess()
{
await Task.Delay(1000);
progressBar1.Value += 3;
}

private async void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 33; i++)
{
await Task.Run(() => LongProcess());
}
}

private async void LongProcess()
{
await Task.Delay(1000);
progressBar1.Value += 3;
}

我意识到返回 Task 的第一个示例更正确,但我不明白为什么将 void 函数包装在 Task.Run 中不会产生相同的结果输出?第一个函数按照我的预期进行,每 1 秒更新一次进度条。第二个代码尝试一次更新所有进度条,导致尝试从多个线程更新相同的 UI 元素时出现问题。

我的假设是,由于 buttonClick 方法等待漫长的过程完成,两组代码都不应允许 progressBar1 更新发生,直到前一个过程完成。为什么第二组代码允许它同时发生?

最佳答案

这不是你想的那样:

await Task.Run(() => LongProcess());

代码正在等待 Task.Run(),但该任务没有任何东西正在等待 LongProcess()。所以 Task.Run() 在这种情况下立即返回。

这实际上是一个未能“一直异步”的有趣示例,因为内联函数本质上隐藏它是异步的事实。事实上,编译器应该警告您没有任何东西在等待 LongProcess(),它会立即返回。

对比一下:

await Task.Run(async () => await LongProcess());

编辑:我刚刚注意到为什么编译器可能没有警告您。正因为如此:

async void

永远、永远、永远不要这样做 :)(好吧,好吧,有一个这样做的正当理由。而且我敢肯定,直到今天,C# 团队都必须支持它它只是出于那个原因。但是除非你遇到那个原因,否则不要这样做。)

始终为异步方法返回一个Task,以便可以等待该方法。

关于c# - await Task 与 await Task.Run(voidMethod),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30580136/

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