在异步函数中,为什么我必须等待?

问题描述:

说我有方法,像这样:在异步函数中,为什么我必须等待?

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

鉴于DoSomethingElseAsync返回Task它似乎像你应该能够做到这一点:

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

但编译器抱怨这一点:

由于'SomeMethod'是返回'Task'的异步方法,因此返回关键字不得后面跟着一个对象表达式。你打算返回'Task<T>'吗?

这是为什么?

+4

@YvetteColomb它不是* this *问题的确切副本。 OP不询问何时使用await。这问''为什么我不能返回任务?' –

+0

@YvetteColomb这不是重复的,你所指的问题是什么时候使用await,这个问是为什么第二个方法不能简单地返回而不是写await,我认为英语非常明确地认定这两者是不同的。 –

+4

在第一个'await DoSomethingAsync();'完成之前 - 方法已经返回给调用者(毕竟它是异步方法)。所以在'await'之后你无法返回特定的值 - 调用者此时已经收到一个返回值并向前移动。 – Evk

它很像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>,如果你使用等待你必须返回T但由于该方法被编译成状态机将无法返回Task<T>,则方法必须返回T。 (对于Task方法无效)

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

+0

这与Evk的评论结合起来很有意义。 虽然我仍然觉得有点dissapointing'等待Thing1();等待Thing2();返回'和'等待Thing1();返回Thing2();'不要简单地编译成相同的代码,因为它仍然是合乎逻辑的(至少在我的脑海里!) – DJL

你应该这样做

private async Task<SomeReturnType> SomeMethod() 
{ 
    return await DoSomethingElseAsync(); 
} 

或者你可以做

private async Task<SomeReturnType> SomeMethod() 
{ 
    SomeReturnType someResult = await DoSomethingAsync(); 
    return someResult; 
} 

您需要指定其键入您的任务回报。 而你必须等待异步任务。

+0

这就是OP的尝试,并没有工作 –

+0

也许尝试返回一个任务。 – Neuxz

+0

请阅读问题和错误信息。你不能*从异步**方法**返回任何东西**。 '异步任务'是一种方法,而不是一种功能。 –

当您使用await - 控制流可能会离开当前的方法并返回给调用者。假设DoSomethingAsync是一些长时间运行的操作。您致电SomeMethodDoSomethingAsync任务已启动,但您不能等待它在该方法内完成 - 否则没有任何内容会成为“异步”。所以控制流程离开Method并且应该向呼叫者提供返回值。返回值是在完成整个SomeMethod时完成的任务。它可以完成有或没有结果(TaskTask<T>返回值)。出于这个原因,你await后返回的内容不能是SomeMethod返回类型 - 它只能是结果型T(如果SomeMethod返回的任务),或者只是简单的return指示的SomeMethod完成,如果返回简单Task

在通常的方法中,return的意思是“从方法中返回该值,如果有的话”。在async方法中,return的含义更改为“将返回的Task的结果设置为该值(如果有)”。

但你不能将二者结合起来:在async Task方法,你不能直接return一个Task。其中一个原因是,如果您使用await版本,则该方法实际上已经返回Task,并且无法返回另一个。

当谈到回国,async Task方法的行为就像一个void方法,因为它仅允许return;,但从来没有return value;