<分区>
在我最近的采访中,有人问我如何在 5.0 版本之前的 C# 中实现异步编程。我回答说,通过使用委托(delegate)的 BeginInvoke()
和 EndInvoke()
方法,我们可以异步调用方法。但面试官似乎并不高兴。所以,当我用谷歌搜索时,有人说这是异步操作而不是异步方法。谁能解释一下我们如何编写 C# 5.0 版本之前的异步方法。
标签 c# asynchronous
<分区>
在我最近的采访中,有人问我如何在 5.0 版本之前的 C# 中实现异步编程。我回答说,通过使用委托(delegate)的 BeginInvoke()
和 EndInvoke()
方法,我们可以异步调用方法。但面试官似乎并不高兴。所以,当我用谷歌搜索时,有人说这是异步操作而不是异步方法。谁能解释一下我们如何编写 C# 5.0 版本之前的异步方法。
最佳答案
异步编程有几种历史方法。
就 BCL 而言,大多数实例都遵循 Asynchronous Programming Model (APM)或 Event-Based Asynchronous Pattern (EAP) (APM 更为常见)。 EAP 通常在幕后使用 SynchronizationContext
以在“上下文”上自动恢复。 APM 不会尝试在“上下文”上恢复。
在 EAP 之前,还有另一种较旧的模式,很少使用,因为它与 WinForms 和整个 Component
系统集成得太紧密了。据我所知,此模式没有名称,但可以通过 SynchronizationObject
属性来识别,您可以将其设置为 ISynchronizeInvoke
的实例(通常是 WinForms 控件)。然后该组件在该 ISynchronizeInvoke
实例的上下文中引发其事件。 BCL 中这种模式的示例很少见,但有一些:System.Timers.Timer
、System.IO.FileSystemWatcher
和 System.Diagnostics。想到过程
。
也可以说任何一种基于事件的系统都是异步的。即使它不遵循 EAP 或 ISynchronizeInvoke
模式,任何可以在未来引发事件以通知订阅者的对象都可以被视为异步组件。
您可以将 Rx(响应式扩展)视为异步编程的超集。 Rx 的字面意思是“事件正确完成”,因此它也可以用于实现异步组件。
最后,还有老式的回调(即 Continuation Passing Style - CPS)。多年前,由于正确实现 APM 或 EAP 的复杂性,这在至少一个 OSS 库中变得有些普遍。官方的 Node.js 异步模式是 CPS,虽然他们现在正在快速转向 async
/await
(官方 API 仍然是 CPS,它被包装到 await
-兼容的 promise )。不管怎样,很多年前有一个特别常见的 .NET OSS 库,它相当普遍并使用 CPS。我的 Google-Fu 让我失望了,但它可能是一个早期的 HTTP 客户端?
以下不是异步编程的例子:
Task.Factory.StartNew
新任务
Delegate.BeginInvoke
ThreadPool.QueueUserWorkItem
新线程
任务[Ex].Run
以上所有只是安排代码在某个地方运行,无论是否在线程池线程上,因此都不是真正的异步。尽管 MSDN 文档“asynchronous delegates”在描述 Delegate.BeginInvoke
时使用了相当困惑的术语,但它只描述了假异步,而不是真正的异步(并且是可能是造成面试困惑的原因)。
伪异步是指一个线程将操作当作是异步的,但实际上该操作只是在不同线程上的同步。有关真正的异步以及为什么它不需要线程的更多信息,请参阅我的博客文章 There Is No Thread .
关于c# - 5.0 之前的 c# 中的异步编程没有 async & await?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38489115/