为了最快的学习。
了解方法执行流程(带有图表):3分钟
在此图像中,仅关注#6(仅此而已)
在#6步骤:执行已在这里用尽,因为它已经用完了。要继续,它需要getStringTask(一种函数)的结果。因此,它使用await
运算符来暂停其进度并将控制权交还给调用方(我们正在使用的此方法)。最初在#2中进行了对getStringTask的实际调用。在#2处承诺返回字符串结果。但是什么时候返回结果呢?我们(#1:AccessTheWebAsync)是否应该再次拨打第二个电话?谁得到结果,#2(调用语句)或#6(等待语句)
AccessTheWebAsync()的外部调用方也正在等待。因此,调用方正在等待AccessTheWebAsync,而AccessTheWebAsync目前正在等待GetStringAsync。有趣的是AccessTheWebAsync在等待之前进行了一些工作(#4),也许是为了节省等待时间。外部呼叫者(和链中的所有呼叫者)也享有相同的多任务自由度,这是“异步”事情的最大优点!您觉得它是同步的..或正常的,但不是。
请记住,该方法已经返回(#2),它无法再次返回(没有第二次)。那么呼叫者怎么知道?一切都与任务有关!任务已通过。等待任务(不是方法,不是值)。值将在“任务”中设置。任务状态将设置为完成。调用方仅监视Task(#6)。所以6#是哪里/谁得到结果的答案。进一步的阅读在这里稍后。
为了学习起见,对问题进行内省:1分钟
让我们稍微调整一下问题:
如何以及何时使用and? async
await
Tasks
因为学习Task
自动涵盖了另外两个(并回答了您的问题)
快速了解语法糖:5分钟
转换前(原始方法)
internal static int Method(int arg0, int arg1)
{
int result = arg0 + arg1;
IO(); // Do some long running IO.
return result;
}
任务定义方法调用上述方法
internal static Task<int> MethodTask(int arg0, int arg1)
{
Task<int> task = new Task<int>(() => Method(arg0, arg1));
task.Start(); // Hot task (started task) should always be returned.
return task;
}
我们提到了等待还是异步?否。调用上述方法,您将获得一个可以监视的任务。您已经知道任务返回什么。整数。
调用Task有点棘手,也就是关键字开始出现时。让我们调用MethodTask()
internal static async Task<int> MethodAsync(int arg0, int arg1)
{
int result = await HelperMethods.MethodTask(arg0, arg1);
return result;
}
上面的相同代码如下图所示:
- 我们正在“等待”完成任务。因此
await
- 由于我们使用等待,因此必须使用
async
(强制语法)
- 以MethodAsync
Async
为前缀(编码标准)
await
很容易理解,但其余两个(async
,Async
)可能不是:)。那么,它应该使很多更有意义的编译器后though.Further读取这里
因此,共有两个部分。
- 创建“任务”
- 创建语法糖来调用任务(
await+async
)
记住,我们有一个AccessTheWebAsync()的外部调用者,并且该调用者也没有幸免...也就是说,它也需要相同的调用者await+async
。和链继续。但是总会有Task
一个结局。
很好,但是一位开发人员惊讶地发现缺少#1(任务)...
分享开发者的困惑:5分钟
开发人员犯了一个错误,即不执行,Task
但仍然可以使用!尝试理解问题,并仅提供此处提供的可接受的答案。希望您已经阅读并完全理解。总结是我们可能看不到/没有实现“任务”,但是它是在父类的某个地方实现的。同样,在我们的示例中,调用一个已构建MethodAsync()
的方法比使用我们自己的Task
(MethodTask()
)方法更容易。大多数开发人员发现,很难Tasks
将代码转换为异步代码。
提示:尝试查找现有的Async实现(例如MethodAsync
或ToListAsync
)以将困难外包。因此,我们只需要处理Async和await(这很简单,与普通代码非常相似)
问题:将真实代码的实际实现快速更改为异步操作:2分钟
下面在数据层中显示的代码行开始中断(很多地方)。因为我们将某些代码从.Net framework 4.2。*更新到了.Net core。我们必须在整个应用程序中在1小时内解决此问题!
var myContract = query.Where(c => c.ContractID == _contractID).First();
十分简单!
- 我们安装了EntityFramework nuget软件包,因为它具有QueryableExtensions。或者换句话说它的异步执行(任务),所以我们可以用简单的生存
Async
和await
代码。
- 命名空间= Microsoft.EntityFrameworkCore
调用代码行像这样更改
var myContract = await query.Where(c => c.ContractID == _contractID).FirstAsync();
方法签名从更改为
Contract GetContract(int contractnumber)
至
async Task<Contract> GetContractAsync(int contractnumber)
调用方法也受到影响:GetContractAsync(123456);
被称为GetContractAsync(123456).Result;
我们在30分钟内到处更改了它!
但是架构师告诉我们不要为此使用EntityFramework库!哎呀!戏剧!然后,我们做了一个自定义的Task实现(yuk)。你知道的。还是容易!..still yuk ..
下一步要去哪里?
我们可以观看一段精彩的快速视频,介绍如何在ASP.Net Core中将同步调用转换为异步,这可能是阅读此书后的发展方向。