根据我的理解, 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
达到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
团队发布了一个很好的常见问题解答 。