简体   繁体   中英

When you use async-await, does it matter where I define the Task and where I await it?

I'm looking at the example method

public async Task MyMethodAsync()
{
    Task<int> longRunningTask = LongRunningOperationAsync();
    // independent work which doesn't need the result of LongRunningOperationAsync can be done here

    //and now we call await on the task 
    int result = await longRunningTask;
    //use the result 
    Console.WriteLine(result);
}

from How and When to use `async` and `await` and I have a question about how it works.

So let's say I add some "independent work" where it says I can.

public async Task MyMethodAsync()
{
    Task<int> longRunningTask = LongRunningOperationAsync();
    int millionthPrimeNumber = GetMillionthPrimeNumber();
    int result = await longRunningTask;
    //use the result 
    Console.WriteLine(result % millionthPrimeNumber);
}

Getting the millionth prime number is independent work and so I expect that it is the type of thing that would be sandwiched between the Task<int> longRunningTask = LongRunningOperationAsync(); and int result = await longRunningTask;

However, what I'm curious about is whether I could just write

public async Task MyMethodAsync()
{
    int result = await LongRunningOperationAsync();
    int millionthPrimeNumber = GetMillionthPrimeNumber();       
    //use the result 
    Console.WriteLine(result % millionthPrimeNumber);
}

and would that be equivalent or not? Or does the Task<int> longRunningTask = LongRunningOperationAsync(); and int result = await longRunningTask; actually serve as flags so that the independent work that can be done is whatever is between them?

Lots of people misunderstand this.

First of all: await does not start a task. Calling the task-returning method starts the task. Await does not cause a method that would be synchronous to magically become asynchronous.

What then does await do? Await means the stuff that follows after this point will not run until some time after the task is completed . That's it. That's what it means. To achieve that, it asynchronously waits for the task to complete. By "asynchronously waits" I mean "returns to the caller so that more work can be done while we're waiting".

If the task produces a value then the await will extract the value from the completed task. Which is perfectly consistent: if code that follows depends on the task's value then it also depends on the task being done!

You should put awaits in your code at the points where the code which follows depends on the awaited task having completed .

would that be equivalent or not?

They are equivalent in that they both eventually produce the same result. They are not equivalent in the sense that they express different asynchronous workflows.

The LongRunningOperationAsync method should contain an I/O bound asynchronous task (such as file system or network access) for the program to benefit from asynchronously waiting. If LongRunningOperationAsync contains only CPU-bound tasks, it's no different, in general, than if the method weren't async .

Think of it this way. If you have this code:

int result = await LongRunningOperationAsync();

...imagine it to be this instead.

int result;
await LongRunningOperationAsync();
//
// Here we leave MyMethodAsync and do other
// work in the meantime. When LongRunningOperationAsync
// finishes...
//

result = /* Result extracted from LongRunningOperationAsync */;

//
// Now we're back to MyMethodAsync and
// move on with the rest of the method using
// the value of `result`.
//

The same is true if LongRunningOperationAsync() is replaced with longRunningTask as in your question.

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