异步任务的 return 值是多少?

What is the return value of async Task?

假设我有这个 async 方法:

public async Task Foo(object fooObj)
{
    //do foo's stuff.
    //maybe set a fooable static global variable
    //or write some data to fooObj
}

并这样称呼它:

public async void FooCaller()
{
    await Foo(new dummyObject)
}

好的,所以:第一个代码块 return 是一个 Task,但它实际上并没有在任何地方被 return 编辑。

我可以想象 async 关键字大小写有一些编译器异常,否则需要 return 值。

但是如果是这样的话,return这个值是怎么初始化的呢? (好的,我可以自己检查)。

更重要的是:

使用这个模式有什么陷阱吗? (例如:访问 fooObj、延迟执行时间等)

Ok, so: this first code block returns a Task, but it isn't actually returned anywhere.

确实如此。你可以把它想象成 Task<void> - 如果它有效的话。它用于指示异步方法何时完成。

基本上,任何非 void 异步方法都会包装您 return 在任务中的任何内容。例如:

async Task<string> FooAsync()
{
    // Do some async operations
    return "foo";
}

注意return语句中表达式的类型是string,但是方法声明的return类型是Task<string>。编译器完成所有工作以将异步操作包装在合适的 Task 中,该操作在方法完成或抛出异常时完成。 (在这种情况下,returned Task 具有 "faulted" 状态。)

之所以需要这样做,是因为在方法 完成 之前,对异步方法的调用通常 returns。将方法调用视为 "Please start doing something" - 它将 启动 它和 return,但您想知道 "something" 何时完成,并且结果是什么。

await 表达式执行相反的 unwrapping - 它只会在等待的操作完成时继续执行该方法,并解包值(例如使用 Task.Result).但是它不会阻塞,而是立即使该方法 return。这就是组合与等待其他异步方法结果的异步方法一起工作的方式。

一旦掌握了 stringTask<string> 包装的窍门,以及 await 任务的等效展开,应该很容易看出与 Taskvoid。因此,正如这对 void 方法有效一样:

void Foo()
{
    // Do some actions.
    ...
    // No need for a return statement
}

async Task 方法等价:

async Task Foo()
{
    // Do some actions (presumably using await)
    ...
    // No need for a return statement
}

可以async Task方法中有一个return语句(没有值):

async Task Foo()
{
    if (weDontNeedToDoAnything)
    {
        return; // This is fine
    }
    // Do some actions (presumably using await)
    ...
    // No need for a return statement
}