为什么异步 I/O 需要事件循环

问题描述 投票:0回答:2

我在 C#/.Net 中进行了大量开发,异步故事从第一天起就一直存在(诚然,API 多年来从开始/结束到事件,到

Task<T>
async
发生了显着变化) /
await
)。在过去一年左右的时间里,我一直在使用 Node.js 进行开发,它异步执行所有 I/O 并使用单线程事件循环模型。最近,我正在开发一个使用 Ruby 的项目,对于应用程序的一部分,我觉得异步发出一大堆 Web 请求是有意义的,并且惊讶地发现 Ruby 中的异步故事非常广泛。不同的。执行任何异步 I/O 的唯一方法是使用
EventMachine

我的问题归结为:为什么在 .Net 中(据我所知这对于 Java/JVM 也是如此)不需要事件循环,并且我可以随时触发异步请求时间,但在像 Ruby/Python 这样的语言中,我需要分别求助于 eventmachine/twisted 吗?我觉得异步 I/O 的工作原理有一些基本问题我不理解。

.net ruby asynchronous eventmachine event-loop
2个回答
12
投票

我的问题归结为:为什么在 .Net 中(以及从何而来) 我可以说这对于 Java/JVM 也是如此)不需要 事件循环,我可以随时触发异步请求, 但在 Ruby/Python 这样的语言中,我需要求助于 eventmachine/twisted 分别?

我认为这是因为 Ruby/Python(以及 Node.js)希望通过为应用程序的核心循环强加单线程模型来让开发人员的生活变得更轻松。使用事件机,异步 I/O 例程的完成回调被序列化并排队在同一线程上执行,因此开发人员不必担心线程安全。

我不能代表 Java,但在 .NET 中,我们可以通过 同步上下文 来控制它。查看 Stephen Cleary 的“一切都是关于 SynchronizationContext”。在 .NET 中复制事件机的概念非常容易(事实上,对于 UI 应用程序来说,这是自动完成的)。序列化同步上下文的自定义实现可能类似于 Stephen Toub 的

“Await、SynchronizationContext 和控制台应用程序”
中的 AsyncPump。 IMO,这将与 Ruby 的事件机器直接匹配。


2
投票

EventMachine
并不是在 Ruby 中进行异步 IO 的唯一方法。您可以派生另一个进程或生成一个新线程。当然后续的沟通也需要你来处理和协调。

EventMachine 只是 Ruby 可用的替代并发实现之一,基于 reactor 模式。它允许在单个进程中实现非阻塞 IO,无需使用任何线程。主要优点是您摆脱了与多线程相关的复杂性,包括死锁、竞争条件、Ruby 臭名昭著的 GIL 和调试噩梦。

.NET 中的

Async 和 Await 提供类似的功能,不需要多线程,而 Task.RunBackgroundWorker 遵循线程方法。

与每个值得思考的问题一样,每种方法都有其优点和用例。如果您打算在后台执行“CPU 限制”操作,您最好生成一个新线程。如果您需要执行IO-bound操作,那么基于反应器的方法将更合适(而且绝对不那么复杂)。

© www.soinside.com 2019 - 2024. All rights reserved.