在C#中,如果一个方法中的任何异步操作使整个方法异步,为什么我需要在该方法中有多个wait语句



为什么一个await语句不让同一方法中的所有其他语句异步等待调用?

来自MS文档:

static async Task<Toast> MakeToastWithButterAndJamAsync(int number)
{
var toast = await ToastBreadAsync(number);
ApplyButter(toast);
ApplyJam(toast);
return toast;
}

页面上写着,

任务组合

除了干杯烤面包是一个异步操作(烤面包(和同步操作(添加黄油和果酱(。更新此代码说明了概念:

重要

由异步操作和同步操作组成工作是一种异步操作。换句话说,如果有任何部分的一个操作是异步的,整个操作也是异步的。

稍后在最终版本中,其中一个方法显示两个等待语句。为什么?如果该方法在Task.Delay上有第一个await,为什么我需要在第二个Task.Delay上有另一个await?难道CCD_ 5不会使这个异步线程";等待";还是在这里?

private static async Task<Bacon> FryBaconAsync(int slices)
{
Console.WriteLine($"putting {slices} slices of bacon in the pan");
Console.WriteLine("cooking first side of bacon...");
await Task.Delay(3000);
for (int slice = 0; slice < slices; slice++)
{
Console.WriteLine("flipping a slice of bacon");
}
Console.WriteLine("cooking the second side of bacon...");
await Task.Delay(3000);
Console.WriteLine("Put bacon on plate");
return new Bacon();
}

这并没有告诉我为什么:为什么我们在C#方法中需要多个"等待"语句?

也不是这个,

具有同步和异步操作的C#异步等待

Task.Delay不会延迟当前任务。它创建另一个等待该数量的任务。因此,如果您只执行Task.Delay(123),则会生成等待123毫秒的另一个任务,但您当前的的任务不会等待生成的完成。为了使当前任务也等待123毫秒,您需要await Task.Delay(123),这将使当前task等待派生的task,等待123毫秒。因为await会暂停目前的task执行,以等待给定的其他task完成。


注意:请注意Theodor Zoulias的评论:

最好说任务。延迟会创建一个任务,该任务将在该时间后完成。内部没有等待。

awaits在那里,以便在工作完成后执行下一条语句。

让我们想象一段需要一系列步骤的代码。

async Task<bool> ProcessAsync() 
{
var data = await GetDataAsync();
await SendDataOrThrowAsync(data);
return true; // Success
}

第一次等待很容易——你不能在得到数据之前发送数据。第二个等待在那里,因此只有当发送完成时才执行return true

没有2号等待合同变更。

async Task<bool> ProcessAsync() 
{
var data = await GetDataAsync();
SendDataOrThrowAsync(toast); // don't wait just start
return true; // Success
}

这里的true意味着我们开始发送,而不是发送。


我认为这也是一个很好的例子,我希望它能帮助消除混乱。

await Task.Delay(1000);
await Task.Delay(2000);
DoWork();

DoWork将在3秒钟后被调用。

await Task.Delay(1000); // Start, and pause execution here until done
Task.Delay(2000); // Start, but don't pause;
DoWork();

DoWork将在1秒后被调用。

有能力去await或不去await可以让你同时做多件事。

async Task<int> GetFirstHalfAsync() => await Task.Delay(1000);
async Task<int> GetSecondHalfAsync() => await Task.Delay(3000);
(...)
var t1 = GetFirstHalfAsync(); // Start, don't pause here
var t2 = GetFirstHalfAsync(); // Start, don't pause here
var results = await Task.WhenAll(new Task<int>[] { t1, t2 }); // Pause here until we get the results 

最新更新