在任务内等待异步/等待

问题描述 投票:0回答:3

我的

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()
的调用完成。 我怎样才能让它真正等待?

c# .net task-parallel-library task async-await
3个回答
114
投票

不鼓励将

Task.Factory.StartNew
async-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 文章:Task.Run 与 Task.Factory.StartNew


9
投票

似乎我通过

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 我想那没问题。


0
投票

我最近遇到了类似的问题,发现你需要做的就是让

DoBar()
返回一些值并使用 .Result 而不是等待。

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

var val = g.Result;

这将等待

func
返回其输出并将其分配给 val。

© www.soinside.com 2019 - 2024. All rights reserved.