栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

如何在.NET中产生并等待实现控制流?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

如何在.NET中产生并等待实现控制流?

我将在下面回答您的特定问题,但是您可能会很容易阅读我关于如何设计产量和等待时间的大量文章。

https://blogs.msdn.microsoft.com/ericlippert/tag/continuation-passing-
style/

https://blogs.msdn.microsoft.com/ericlippert/tag/iterators/

https://blogs.msdn.microsoft.com/ericlippert/tag/async/

这些文章中有些已经过时了。生成的代码在很多方面都不同。但是,这些肯定会让您了解其工作原理。

另外,如果您不了解lambda如何作为闭包类生成,请 首先 了解。如果您没有lambda,那么您就不会做出异步的事情。

当到达等待状态时,运行时如何知道下一步应执行什么代码?

await
生成为:

if (the task is not completed)  assign a delegate which executes the remainder of the method as the continuation of the task  return to the callerelse  execute the remainder of the method now

基本上就是这样。等待只是幻想的回报。

它如何知道何时可以从上次中断的地方恢复,以及如何记住在哪里?

好吧,您如何在 不 等待的 情况下
做到这一点?当方法foo调用方法bar时,无论如何执行bar,我们都以某种方式记得如何回到foo的中间,而激活foo的所有本地语言都保持不变。

您知道在汇编程序中是如何完成的。foo的激活记录被压入堆栈;它包含本地人的值。在调用时,将foo中的返回地址压入堆栈。完成bar之后,堆栈指针和指令指针将重置为所需的位置,而foo将从其中断处继续运行。

等待的继续是完全相同的,除了将记录放到堆上是出于明显的原因,即 激活序列没有形成堆栈 。

等待任务继续执行的委托包含(1)一个数字,该数字是查找表的输入,该表提供了下一步需要执行的指令指针,以及(2)所有locals和temparies的值。

那里还有一些其他装备;例如,在.NET中,分支到try块的中间是非法的,因此您不能简单地将try块内的代码地址粘贴到表中。但是这些是簿记细节。从概念上讲,激活记录只是移到堆上。

当前调用堆栈发生了什么,是否以某种方式保存了它?

当前激活记录中的相关信息永远不会放在栈上。它是从一开始就从堆中分配的。(嗯,形式参数通常在堆栈上或寄存器中传递,然后在方法开始时复制到堆位置。)

呼叫者的激活记录未保存;请记住,等待可能会回到他们身边,所以他们将得到正常处理。

请注意,这是简化的继续等待传递样式与您在诸如Scheme之类的语言中看到的真正的当前循环调用结构之间的紧密区别。在这些语言中,整个延续(包括回到呼叫者的延续)由call-
cc捕获。

如果调用方法在等待之前进行其他方法调用,怎么办?为什么堆栈不被覆盖?

这些方法调用返回,因此在等待时它们的激活记录不再在堆栈上。

在异常和堆栈展开的情况下,运行时到底将如何处理所有这些问题?

如果发生未捕获的异常,则捕获该异常并将其存储在任务中,并在获取任务的结果时将其重新抛出。

还记得我之前提到的所有簿记吗?让我告诉你,正确设置异常语义是一个巨大的痛苦。

当达到产量时,运行时如何跟踪应该拾取的点?迭代器状态如何保存?

同样的方式。当地人的状态被移到堆上,并且代表该指令的数字

MoveNext
在下一次被调用时应在该指令处重新存储。

同样,在迭代器块中还有很多工具可以确保正确处理异常。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/430418.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号