且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何以及何时使用“异步”和“等待”

更新时间:2022-12-15 21:25:37

使用 async 和 await ,编译器会在后台生成状态机。

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:


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

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

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

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

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

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

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.