如何和何时使用 "async" 和 "await"

41 浏览
0 Comments

如何和何时使用 "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 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 DoSomethingAsync()
{
    // is this executed on a background thread?
    System.Threading.Thread.Sleep(5000);
    return 1;
}

admin 更改状态以发布 2023年5月21日
0
0 Comments

根据我的理解,async和await的主要作用之一是使代码易于编写和阅读。

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

这和生成后台线程来执行长时间逻辑的操作是一样的吗?

完全不是。

//我不明白为什么这个方法必须标记为'async'。

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

//这一行在从DoSomethingAsync()方法的5秒睡眠后到达。它不应该立即到达吗?

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

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

不是。


您可能会发现我介绍的 async/await 有所帮助。官方的 MSDN 文档也非常好(特别是 TAP 部分),而 async 团队发布了一份优秀的 FAQ

0
0 Comments

使用asyncawait时,编译器会在后台生成一个状态机。

下面是一个示例,我希望能在其中解释一些正在进行的高级细节:

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

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

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

  2. 假设在主线程(线程ID = 1)上独立进行工作,然后到达await longRunningTask

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

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

0