【问题标题】:Correctly awaiting Task.Run with async lambda expression使用异步 lambda 表达式正确等待 Task.Run
【发布时间】:2026-01-05 08:45:01
【问题描述】:

所以我在 Task.Run 中有一个异步方法,如下所示:

//SynchronisationContext = UI Thread
await Task.Run(async => 
{
    for (int i = 0; i < 100; i++)
    {
       var res = ComplicatedCalulation(); //Takes about 1 second
       await ThirdPartyLib.WriteToDatabase(res);
    }
});

上述代码中的 await 是等待异步 lambda 代码还是只是等待 Task 启动(即立即返回)

我知道Task.Factory.StartNew的正确用法是

await Task.Factory.StartNew&lt;Task&gt;(async =&gt; await MyAsyncMethod()).Result

Task.Run 也是如此吗?

【问题讨论】:

  • 也许这个(及其相关链接)作者是 Stephen Cleary*.com/questions/32591462/…
  • Task.Result 很少是正确的选择,以至于我发现自己在这里质疑它是否真的是“正确使用”......
  • @TheGeneral 我不确定它是否正确。他的建议是避免这种情况,但我认为我有一个有效的用途。我在Task 方法中添加了一些上下文
  • StartNew 示例应使用Unwrap,而不是Result。另外,我强烈建议始终将TaskScheduler 传递给StartNew。或者,更好的是,只需使用 Task.Run,它会为您完成这两项工作。

标签: c# async-await task


【解决方案1】:

您的代码将使用任务机制等到计算结束。这不会阻塞您的线程,但在循环中的所有内容完成之前,它不会执行超出此点的代码。

public static async Task Test()
{
    await Task.Run(async () => 
    {
        for (int i = 0; i < 10; i++)
        {
            await Task.Delay(TimeSpan.FromSeconds(1));
            Console.WriteLine($"inside {i}");
        }
    });
    Console.WriteLine("Done");
}

将给出以下输出:

inside 0
inside 1
inside 2
inside 3
inside 4
inside 5
inside 6
inside 7
inside 8
inside 9
Done

【讨论】: