异步任务的返回值是多少?

时间:2015-02-26 11:25:26

标签: c# .net async-await

想象一下,我有这个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)
}

好的,所以:第一个代码块返回Task,但它实际上并没有返回任何地方。

我可以想象async关键字的情况有一些编译器异常,否则需要返回值。

但如果是这种情况,返回值如何初始化? (好吧,我可以自己检查一下)。

更重要的是:

使用此模式时是否存在任何陷阱? (例如:访问fooObj,延迟执行时间等。)

1 个答案:

答案 0 :(得分:8)

  

好的,所以:第一个代码块返回一个Task,但它实际上并没有返回任何地方。

事实上。您可以将其视为Task<void> - 如果它是有效的。它用于指示异步方法何时完成。

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

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

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

需要这样做的原因是,在方法完成之前,对异步方法的调用通常返回。将方法调用视为“请开始做某事” - 它将启动并返回,但您想知道“某事”何时完成,以及结果是什么。

await表达式执行相反的展开 - 它只会在等待操作完成时继续通过该方法,并打开该值(例如使用Task.Result)。但它不会阻塞,而是会立即返回。这就是组合如何与等待其他异步方法的结果的异步方法很好地协作。

一旦你完成了stringTask<string>包装以及等同的解包,如果你await这个任务,就应该很容易看到{{1}的类比}和Task。因此,这对void方法有效:

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 } 方法中使用return语句(没有值):

async Task