如何以及何时使用`async`和`await`
根据我的理解, async
和await
的主要事情之一是使代码易于编写和读取 - 但是使用它们等同于产生后台线程来执行长期逻辑?
我目前正在尝试最基本的例子。 我在内部添加了一些评论。 你能为我澄清一下吗?
// 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;
}
当使用async
并await
编译器在后台生成状态机时。
这里有一个例子,我希望我能解释一些正在进行的高级细节:
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。