简体   繁体   中英

In async function why do I have to await?

Say I have method such as this:

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

Given that DoSomethingElseAsync returns a Task it would seem like you should be able to do this:

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

but the compiler complains about this:

Since ' SomeMethod ' is an async method that returns ' Task ', a return keyword must not be followed by an object expression. Did you intend to return ' Task<T> '?

Why is that?

Its pretty much like how yield return and return works. for an iterator you have either of these methods

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.
}

but you cant have both. it doesn't work, because an iterator is either converted to a class by compiler to handle lazy iteration with yield , or its just like other normal methods that returns something else.

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

The story is same about return and async/await . for method that has return type of Task you either return Task or use async/await .

for Task<T> if you use await you must return T but you can not return Task<T> because the method is compiled into state machine, then method must return T . (for Task method is void)

if you don't use async/await method will be exactly like other normal methods.

When you use await - control flow might leave current method and return back to the caller. Suppose DoSomethingAsync is some long running operation. You call SomeMethod . DoSomethingAsync task is started but then you cannot wait for it to complete inside that method - otherwise nothing will be "async". So control flow leaves Method and should provide a return value to the caller. Return value is a task which completes when whole SomeMethod is completed. It can complete with or without result ( Task or Task<T> return value). For that reason what you return after await could not be return type of SomeMethod - it can only be result type T (if SomeMethod returns Task) or just simple return to indicate completion of SomeMethod if it returns simple Task .

In a normal method, return means "return this value, if any, from the method". In an async method, the meaning of return is changed to "set the result of the returned Task to this value, if any".

But you can't combine the two: in an async Task method, you can't directly return a Task . One reason for this is that if you await ed, the method actually already returned a Task and it can't return another one.

When it comes to returning, async Task method behaves like a void method, in that it only allows return; , but never return value; .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM