How and When to use `async` and `await`

From my understanding one of the main things that async and await do is to make code easy to write and read - but is using them equal to spawning background threads to perform long duration logic?

I'm currently trying out the most basic example. I've added some comments inline. Can you clarify it for me?

// I don't understand why this method must be marked as `async`.
private async void button1_Click(object sender, EventArgs e)
{
    Task<int> access = DoSomethingAsync();
    // task independent stuff here

    // this line is reached after the 5 seconds sleep from 
    // DoSomethingAsync() method. Shouldn't it be reached immediately? 
    int a = 1; 

    // from my understanding the waiting should be done here.
    int x = await access; 
}

async Task<int> DoSomethingAsync()
{
    // is this executed on a background thread?
    System.Threading.Thread.Sleep(5000);
    return 1;
}

When using async and await the compiler generates a state machine in the background.

Here's an example on which I hope I can explain some of the high-level details that are going on:

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);
}

public async Task<int> LongRunningOperationAsync() // assume we return an int from this long running operation 
{
    await Task.Delay(1000); // 1 second delay
    return 1;
}

OK, so what happens here:

  • Task<int> longRunningTask = LongRunningOperationAsync(); starts executing LongRunningOperation

  • Independent work is done on let's assume the Main Thread (Thread ID = 1) then await longRunningTask is reached.

    Now, if the longRunningTask hasn't finished and it is still running, MyMethodAsync() will return to its calling method, thus the main thread doesn't get blocked. When the longRunningTask is done then a thread from the ThreadPool (can be any thread) will return to MyMethodAsync() in its previous context and continue execution (in this case printing the result to the console).

  • A second case would be that the longRunningTask has already finished its execution and the result is available. When reaching the await longRunningTask we already have the result so the code will continue executing on the very same thread. (in this case printing result to console). Of course this is not the case for the above example, where there's a Task.Delay(1000) involved.


    Further to the other answers, have a look at await (C# Reference)

    and more specifically at the example included, it explains your situation a bit

    The following Windows Forms example illustrates the use of await in an async method, WaitAsynchronouslyAsync. Contrast the behavior of that method with the behavior of WaitSynchronously. Without an await operator applied to a task, WaitSynchronously runs synchronously despite the use of the async modifier in its definition and a call to Thread.Sleep in its body.

    private async void button1_Click(object sender, EventArgs e)
    {
        // Call the method that runs asynchronously.
        string result = await WaitAsynchronouslyAsync();
    
        // Call the method that runs synchronously.
        //string result = await WaitSynchronously ();
    
        // Display the result.
        textBox1.Text += result;
    }
    
    // The following method runs asynchronously. The UI thread is not
    // blocked during the delay. You can move or resize the Form1 window 
    // while Task.Delay is running.
    public async Task<string> WaitAsynchronouslyAsync()
    {
        await Task.Delay(10000);
        return "Finished";
    }
    
    // The following method runs synchronously, despite the use of async.
    // You cannot move or resize the Form1 window while Thread.Sleep
    // is running because the UI thread is blocked.
    public async Task<string> WaitSynchronously()
    {
        // Add a using directive for System.Threading.
        Thread.Sleep(10000);
        return "Finished";
    }
    

    From my understanding one of the main things that async and await do is to make code easy to write and read.

    They're to make asynchronous code easy to write and read, yes.

    Is it the same thing as spawning background threads to perform long duration logic?

    Not at all.

    //i don't uderstand why this method must be marked as "async'.

    The async keyword enables the await keyword. So any method using await must be marked async .

    // this line is reached after the 5 seconds sleep from DoSomethingAsync() method. Shouldn't it be reached immediately?

    No, because async methods are not run on another thread by default.

    //is this executed on a background thread?

    No.


    You may find my async / await intro helpful. The official MSDN docs are also unusually good (particularly the TAP section), and the async team put out an excellent FAQ.

    链接地址: http://www.djcxy.com/p/30810.html

    上一篇: 我可以使用std :: async而不用等待将来的限制吗?

    下一篇: 如何以及何时使用`async`和`await`