.NET 中 yield
和 await
的控制流机制
对 .NET 中 yield
和 await
关键字的理解,你的认识大体正确。yield
允许迭代器块将控制权返回给调用代码,并在再次调用迭代器时从中断处继续执行。await
不仅等待被调用方完成,还将控制权返回给调用方。当调用方再次 await
该方法时,执行将从中断处恢复。
理解这些结构的关键在于它们的实现机制。对于 await
,它本质上等同于一个“高级返回”。当遇到 await
表达式时,运行时会检查任务是否已完成。如果未完成,它会分配一个委托,将方法的剩余部分作为任务的延续执行,并返回给调用方。如果任务已完成,则立即执行方法的剩余部分。
await
的延续包含一个数字,该数字在一个查找表中标识接下来要执行的指令指针。这确保了当任务恢复时,它可以从正确的位置继续执行。延续还存储所有局部变量和临时变量的值,允许方法恢复执行,就好像它从未被中断一样。
至于运行时如何在 await
之前处理多个方法调用的问题,答案在于调用方的激活记录及其调用的方法的激活记录并非存储在同一个堆栈中。相反,await
恢复的相关信息存储在堆上。这确保了堆栈不会被后续方法调用覆盖。
如果发生未处理的异常,则会捕获该异常并将其存储在任务中。当获取任务的结果时,会重新抛出该异常。这种行为确保即使在存在异步操作的情况下也能正确处理异常。
类似的原理也适用于 yield
的实现。当迭代器块 yield
一个值时,局部变量的状态以及表示 MoveNext
应该在下次调用迭代器时恢复执行的指令的数字会被复制到堆上。这允许迭代器在 yield
点暂停执行,并在以后恢复执行而不会丢失任何状态。
通过利用这些复杂的机制,yield
和 await
关键字提供了一种强大的方法来在 .NET 中实现异步和迭代操作。它们允许在无需线程的情况下模拟并发,从而简化代码并提高性能。
以上是`yield` 和 `await` 如何管理 .NET 中的控制流?的详细内容。更多信息请关注PHP中文网其他相关文章!