为了最快的学习..
理解方法执行流程(用图表):3分钟
问题自省(为了学习):1分钟
快速浏览语法糖:5分钟
分享开发人员的困惑:5分钟
问题:快速将正常代码的实际实现更改为
异步代码:2分钟
下一步何去何从?
理解方法执行流程(用图表):3分钟
在这张图中,只关注#6(没有其他)
在第6步,执行工作耗尽并停止。要继续,它需要getStringTask(一种函数)的结果。因此,它使用await操作符来暂停进程,并将控制权交还给调用者(我们所在的方法)。对getStringTask的实际调用是在#2前面进行的。在#2中,承诺返回一个字符串结果。但是它什么时候会返回结果呢?我们应该(#1:AccessTheWebAsync)再次进行第二次调用吗?谁得到结果,#2(调用语句)还是#6(等待语句)?
AccessTheWebAsync()的外部调用者现在也在等待。调用者等待AccessTheWebAsync,而AccessTheWebAsync正在等待GetStringAsync。有趣的是AccessTheWebAsync在等待之前做了一些工作(#4),可能是为了节省等待的时间。同样的多任务自由也适用于外部调用者(以及链中的所有调用者),这是这个“异步”东西的最大优点!你觉得这是同步的,或者是正常的,但事实并非如此。
#2和#6被分开了,所以我们有#4的优势(边等待边工作)。但我们也可以不分裂。因此,#2将是:string urlContents = await client.GetStringAsync("…");这里我们没有看到任何优势,但在链的某个地方,一个函数将被分裂,而其他函数将调用它而不分裂。这取决于你使用链中的哪个函数/类。从一个函数到另一个函数的行为变化是本主题中最令人困惑的部分。
记住,该方法已经返回(#2),它不能再次返回(没有第二次)。那么,调用者如何知道呢?这都是关于任务!任务返回。等待任务状态(不是方法,不是值)。值将在任务中设置。任务状态将被设置为完成。调用者只监视任务(#6)。所以6#是在哪里/谁得到结果的答案。进一步阅读请点击这里。
为学习而反思问题:1分钟
让我们稍微调整一下这个问题:
如何以及何时使用async和await任务?
因为学习任务自动涵盖了其他两个(并回答了你的问题)。
整个想法非常简单。方法可以返回任何数据类型(double, int, object等),但在这里我们只是拒绝这一点,并强制返回一个'Task'对象!但我们仍然需要返回的数据(除了void),对吗?这将在'Task'对象中的标准属性中设置,例如:'Result'属性。
快速浏览语法糖:5分钟
原始的非异步方法
int方法(int arg0, int arg1)
{
Int result = arg0 + arg1;
IO ();//执行一些长时间运行的IO。
返回结果;
}
一个全新的Task-ified方法来调用上面的方法
内部静态任务<int> MethodTask(int arg0, int arg1)
{
Task<int> Task = new Task<int>(() => Method(arg0, arg1));
task.Start ();// Hot task(已启动的任务)应该总是返回。
返回任务;
}
我们提到await或async了吗?不。调用上面的方法,就可以得到一个可以监视的任务。您已经知道任务返回(或包含)什么。一个整数。
调用Task有点棘手,这是关键字开始出现的时候。如果有一个方法调用原始方法(非异步),那么我们需要按照下面所示编辑它。让我们调用MethodTask()
内部静态异步任务<int> MethodAsync(int arg0, int arg1)
{
int result = await HelperMethods。MethodTask (arg0, __arg1);
返回结果;
}
与上图相同的代码:
我们正在“等待”完成任务。因此使用await(强制语法)
因为使用了await,所以必须使用async(强制语法)
以Async为前缀的MethodAsync(编码标准)
await很容易理解,但其余两个(async, async)可能不是:)。好吧,这对编译器来说应该更有意义。进一步阅读请点击这里
所以有两个部分。
创建“任务”(只有一个任务,它将是一个额外的方法)
创建使用await+async调用任务的语法糖(如果要转换非异步方法,则需要更改现有代码)
记住,我们有一个外部调用AccessTheWebAsync()和调用者也没有幸免…也就是说,它也需要相同的await+async。这个链条还在继续(因此这是一个突破性的变化,可能会影响许多职业)。它也可以被认为是一个非破坏性的更改,因为原始方法仍然在那里等待调用。如果您想进行破坏性更改,则更改它的访问权限(或删除并将其移动到任务中),然后类将被迫使用task -method。无论如何,在异步调用中,总是在一端有一个任务,而且只有一个。
一切都好,但是有一个开发人员对Task感到惊讶
失踪……
分享开发人员的困惑:5分钟
开发人员犯了一个错误,没有实现Task,但它仍然可以工作!试着理解问题和这里提供的公认答案。希望你已经阅读并完全理解。总的来说,我们可能没有看到/实现“Task”,但它在父类/关联类的某个地方实现了。同样,在我们的例子中,调用一个已经构建的MethodAsync()要比自己用Task(MethodTask())实现该方法容易得多。大多数开发人员发现在将代码转换为异步代码时很难理解任务。
提示:尝试寻找一个现有的异步实现(如MethodAsync或ToListAsync)来外包这个困难。所以我们只需要处理Async和await(这很简单,非常类似于正常的代码)
问题:快速将正常代码的实际实现更改为
异步操作:2分钟
数据层中显示的代码行开始中断(许多地方)。因为我们从。net framework 4.2中更新了一些代码。*到。net核心。我们必须在1小时内修复整个应用程序!
var myContract = query.Where(c => c.ContractID == _contractID).First();
easypeasy !
我们安装了EntityFramework nuget包,因为它有QueryableExtensions。或者换句话说,它执行异步实现(任务),所以我们可以在代码中使用简单的Async和等待。
namespace =微软。EntityFrameworkCore
呼叫代码行是这样改变的
var myContract = await query.Where(c => c.ContractID == _contractID).FirstAsync();
方法签名从
GetContract(int contractnumber)
to
async Task<Contract> GetContractAsync(int contractnumber)
调用方法也受到影响:GetContract(123456);GetContractAsync(123456).Result;
等等!结果是什么?好赶上!GetContractAsync只返回一个任务而不是我们想要的值(合约)。一旦操作的结果可用,它就会被存储,并在后续调用result属性时立即返回。
我们也可以用类似的'Wait()'来实现超时
TimeSpan ts = TimeSpan. frommilliseconds (150);
如果(!t.Wait (ts))
控制台。WriteLine("超时间隔已过");
我们在30分钟内把它换遍了所有地方!
但是架构师告诉我们不要仅为此使用EntityFramework库!哦!戏剧!然后我们创建了一个自定义的Task实现。你知道怎么做。还容易!..还咯咯大笑。
下一步何去何从?
我们可以观看一个关于在ASP中将同步调用转换为异步调用的视频。Net Core,也许这是读了这篇文章后人们会去的方向。或者我解释得够多了吗?;)