我在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如何工作的基本问题,我不理解。
答案 0 :(得分:7)
我的问题归结为:为什么在.Net(以及从什么 我可以说Java和JVM也是如此)没有必要 事件循环,我可以随时触发异步请求, 但是在像Ruby / Python这样的语言中,我需要求助于 eventmachine / twisted分别?
我认为这是因为Ruby / Python(以及无缝地,Node.js)希望通过为应用程序的核心循环强加单线程模型来简化开发人员的生活。使用事件机器,异步I / O例程的完成回调被序列化并排队以在同一线程上执行,因此开发人员不必担心线程安全。
我无法代表Java,但在.NET中,我们可以通过同步上下文来控制它。查看Stephen Cleary的"It's All About the SynchronizationContext"。在.NET中复制事件机器的概念非常容易(实际上,这是为UI应用程序自动完成的)。序列化同步上下文的自定义实现可能类似于Stephen Toub的"Await, SynchronizationContext, and Console Apps"中的AsyncPump
。 IMO,这将与Ruby的事件机器直接匹配。
答案 1 :(得分:2)
EventMachine
不是在Ruby中执行异步IO的唯一方法。您可以分叉另一个进程或生成一个新线程。当然,您需要处理和协调后续通信。
EventMachine只是Ruby可用的替代并发实现之一,基于reactor pattern。它允许在单个进程中使用非阻塞IO,而不使用任何线程。主要优点是你摆脱了complexity associated with multithreading,包括死锁,竞争条件,Ruby臭名昭着的GIL,以及调试噩梦。
.NET中的Async and Await提供了类似的功能,不需要多线程,而Task.Run或BackgroundWorker遵循线程方法。
正如每个值得思考的问题一样,每种方法都有其优点和用例。如果您打算在后台执行 CPU绑定操作,最好生成一个新线程。如果您需要执行 IO-bound 操作,那么基于反应堆的方法将更合适(并且肯定不那么复杂)。