协慌网

登录 贡献 社区

如何以及何时使用'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;
}

好的,所以这里发生了什么:

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

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

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

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

进一步回答其他问题,看看等待(C#参考)

更具体地说,在所包含的例子中,它解释了你的情况

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

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 做的主要事情之一是使代码易于编写和读取。

它们是为了使异步代码易于编写和读取,是的。

与产生后台线程执行长持续时间逻辑是一回事吗?

一点也不。

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

async关键字启用await关键字。因此,任何使用await方法都必须标记为async

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

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

// 这是在后台线程上执行的吗?

没有。


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