如何以及何时使用`async`和`await`

根据我的理解, asyncawait的主要事情之一是使代码易于编写和读取 - 但是使用它们等同于产生后台线程来执行长期逻辑?

我目前正在尝试最基本的例子。 我在内部添加了一些评论。 你能为我澄清一下吗?

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

当使用asyncawait编译器在后台生成状态机时。

这里有一个例子,我希望我能解释一些正在进行的高级细节:

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

好的,那么这里发生了什么:

  • Task<int> longRunningTask = LongRunningOperationAsync(); 开始执行LongRunningOperation

  • 独立工作完成后让我们假设主线程(线程ID = 1),然后await longRunningTask达到。

    现在,如果longRunningTask尚未完成且仍在运行,则MyMethodAsync()将返回其调用方法,因此主线程不会被阻止。 当longRunningTask完成时,ThreadPool(可以是任何线程)的线程将返回到其上一个上下文中的MyMethodAsync() ,并继续执行(在这种情况下将结果打印到控制台)。

  • 第二种情况是longRunningTask已经完成执行并且结果可用。 当到达await longRunningTask我们已经有了结果,所以代码将继续在同一个线程上执行。 (在这种情况下将结果打印到控制台)。 当然这不是上述例子的情况,其中涉及Task.Delay(1000)


    进一步的其他答案,看看等待(C#参考)

    更具体地说就是包含的例子,它解释了你的情况

    以下Windows窗体示例说明了如何在异步方法WaitAsynchronouslyAsync中使用await。 将该方法的行为与WaitSynchronously的行为进行对比。 如果没有等待运算符应用于任务,则尽管在其定义中使用了异步修饰符并且在其正文中调用了Thread.Sleep,但WaitSynchronously仍会同步运行。

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

    根据我的理解,异步和等待的主要事情之一是使代码易于编写和阅读。

    他们让异步代码易于编写和读取,是的。

    与产卵后台线程执行长时间逻辑相同吗?

    一点也不。

    //我不明白为什么这个方法必须标记为“异步”。

    async关键字启用了await关键字。 所以任何使用await方法都必须标记为async

    //在DoSomethingAsync()方法的5秒钟睡眠后达到此行。 不应该立即达到?

    不,因为async方法默认情况下不在另一个线程上运行。

    //是否在后台线程上执行?

    没有。


    你可能会发现我的async / await介绍很有帮助。 官方的MSDN文档也非常好(特别是TAP部分), async团队发布了一个出色的FAQ。

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

    上一篇: How and When to use `async` and `await`

    下一篇: What is the issue with std::async?