我注意到.NET 4.0中的一种新趋势,特别是在潜在的多线程场景中,它避免了事件,并提供了订阅者方法。
例如,System.Threading.Tasks.Task和Task<TResult>
有ContinueWith()个方法,而不是已完成或已完成的事件。另一个例子是System.Threading.CancellationToken:它有一个Register()方法而不是CancellationRequested事件。
虽然Task.ContinueWith()是合乎逻辑的,因为它允许简单的任务链(对于事件不会如此优雅),并且它还允许Task<TResult>
从Task
继承(因为这样,Task<TResult>
可以提供适当的重载,这对事件来说是不可能的:如果事件中的事件EventHandler已完成,那么您所能做的就是创建另一个事件,比如,事件{ {1}}在EventHandler<TaskResultEventArgs>
完成,这不是很好),但我找不到与CancellationToken.Register()相同的解释。
那么,类似场景中事件的缺点是什么?我也应该遵循这种模式吗?澄清一下,我应该选择以下哪一项?我什么时候应该更喜欢另一个呢?
Task<TResult>
非常感谢!
答案 0 :(得分:2)
我想使用订阅者方法的一个好处是,您可以轻松指定代理将在其上执行的线程。请参阅CancellationToken.Register()的this overload。
Upd:嗯,实际上你可以指定你的代表将被发布到的同步上下文。
你对这种倾向是正确的。 MSDN杂志中的This article声明如下:
新组件不应该使用 基于事件的异步模式。该 Visual Studio异步社区 技术预览(CTP)包括一个 描述基于任务的文档 异步模式,其中 组件返回任务和 任务对象而不是 通过提高事件 的SynchronizationContext。基于任务 API是异步的未来 用.NET编程。
文章中提到的document
启动和完成 TAP中的异步操作是 用单一方法表示,和 因此,只有一种方法可以命名。 这与之形成鲜明对比 IAsyncResult模式或APM模式, 其中BeginMethodName和 EndMethodName方法是必需的, 与基于事件的情况相反 异步模式,或EAP,其中a 需要MethodNameAsync 除了一个或多个事件,事件 处理程序委托类型和 EventArg派生类型。
事实上,照顾一件事而不是很多事情是件好事。但这比TAP优于EAP更有优势,而不是订户方法的优势。