在异步功能中我为什么要等待?

时间:2017-10-10 08:52:02

标签: c# async-await

说我有这样的方法:

private async Task SomeMethod()
{
  await DoSomethingAsync();
  await DoSomethingElseAsync();
  return;
}

鉴于DoSomethingElseAsync返回Task,您似乎应该可以执行此操作:

private async Task SomeMethod()
{
  await DoSomethingAsync();
  return DoSomethingElseAsync();
}

但是编译器抱怨这个:

  

自&#39; SomeMethod&#39;是一个返回&#39; Task&#39;的异步方法,返回关键字后面不能跟一个对象表达式。您打算退回&#39; Task<T>&#39;?

为什么?

3 个答案:

答案 0 :(得分:5)

yield returnreturn的工作原理非常相似。对于迭代器,您可以使用这些方法之一

public IEnumerable<int> SomeIterator()
{
    for(int I = 0; I < 10; I++) yield return I;
}

public IEnumerable<int> SomeIterator()
{
    return Enumerable.Range(0, 10); // return result of another iterator.
}
但是你不能同时拥有这两个。它不起作用,因为迭代器要么被编译器转换为类来处理使用yield的延迟迭代,要么就像其他返回其他东西的常规方法一样。

public IEnumerable<int> SomeIterator() // not valid
{
    for(int I = 0; I < 10; I++) yield return I;
    return Enumerable.Range(0, 10); 
}

returnasync/await的情况相同。对于返回类型为Task的方法,您可以返回Task或使用async/await

对于Task<T>如果使用await,则必须返回T,但不能返回Task<T>,因为该方法已编译到状态机,然后方法必须返回T。 (对于Task方法无效)

如果您不使用async/await方法,则与其他常规方法完全相同。

答案 1 :(得分:0)

使用await时 - 控制流可能会保留当前方法并返回给调用者。假设DoSomethingAsync是一些长时间运行的操作。你打电话给SomeMethodDoSomethingAsync任务已启动,但您无法等待它在该方法内完成 - 否则将无法执行任何&#34; async&#34;。因此控制流离开Method并应向调用者提供返回值。返回值是在完成整个SomeMethod时完成的任务。它可以在有或没有结果的情况下完成(TaskTask<T>返回值)。因此,await之后返回的内容不能是SomeMethod的返回类型 - 它只能是结果类型T(如果SomeMethod返回任务)或只是简单{{如果return返回简单SomeMethod,则表示Task已完成。

答案 2 :(得分:0)

在常规方法中,return表示&#34;从方法&#34;中返回此值(如果有)。在async方法中,return的含义更改为&#34;将返回的Task的结果设置为此值(如果有)&#34;。

但是你不能将两者结合起来:在async Task方法中,你不能直接return一个Task。这样做的一个原因是,如果您await编辑,该方法实际上已经返回Task,并且无法返回另一个。

在返回时,async Task方法的行为类似于void方法,因为它只允许return;,但绝不允许return value;