在任务中等待async/await

本文关键字:await async 等待 任务 | 更新日期: 2023-09-27 18:13:06

我在main()中有这个结构,它创建了

var tasks = new List<Task>();
var t = Task.Factory.StartNew(
    async () =>
    {
        Foo.Fim();
        await Foo.DoBar();
    });
//DoBar not completed
t.Wait();
//Foo.Fim() done, Foo.DoBar should be but isn't

然而,当我将.Wait替换为t时,它不会等待对DoBar()的调用完成。我如何让它真正等待?

在任务中等待async/await

不鼓励使用Task.Factory.StartNewasync-await,您应该使用Task.Run代替:

var t = Task.Run(
    async () =>
    {
        Foo.Fim();
        await Foo.DoBar();
    });

Task.Factory.StartNew api是在基于任务的异步模式(TAP)和async-await之前构建的。它将返回Task<Task>,因为您正在启动一个带有lambda表达式的任务,该表达式恰好是异步的,因此返回一个任务。Unwrap将提取内部任务,但Task.Run将隐式地为您完成。


要进行更深入的比较,总有一篇相关的Stephen Toub文章:任务。Run vs Task.Factory.StartNew

似乎我通过Unwrap()任务获得了所需的功能。我不太确定我明白这背后的原因,但我想它是有效的。

var t = Task.Factory.StartNew(
            async () =>
                {
                        Foo.Fim();
                        await Foo.DoBar();
                }).Unwrap();

编辑:我已经找了Unwrap()的描述:Creates a proxy Task that represents the asynchronous operation of a Task<Task<T>>我认为这是传统的任务所做的,但如果我需要调用unwrap,我认为这很好。

我最近遇到了类似的问题,并发现所有你需要做的就是让DoBar()返回一些值并使用. result而不是等待。

var g = Task.Run(() => func(arg));
var val = g.Result;

这将等待func返回其输出并将其赋值给val。