订阅者方法与事件

时间:2011-06-15 10:28:54

标签: c# .net multithreading .net-4.0 thread-safety

我注意到.NET 4.0中的一种新趋势,特别是在潜在的多线程场景中,它避免了事件,并提供了订阅者方法。

例如,System.Threading.Tasks.TaskTask<TResult>ContinueWith()个方法,而不是已完成或已完成的事件。另一个例子是System.Threading.CancellationToken:它有一个Register()方法而不是CancellationRequested事件。

虽然Task.ContinueWith()是合乎逻辑的,因为它允许简单的任务链(对于事件不会如此优雅),并且它还允许Task<TResult>Task继承(因为这样,Task<TResult>可以提供适当的重载,这对事件来说是不可能的:如果事件中的事件EventHandler已完成,那么您所能做的就是创建另一个事件,比如,事件{ {1}}在EventHandler<TaskResultEventArgs>完成,这不是很好),但我找不到与CancellationToken.Register()相同的解释。

那么,类似场景中事件的缺点是什么?我也应该遵循这种模式吗?澄清一下,我应该选择以下哪一项?我什么时候应该更喜欢另一个呢?

Task<TResult>

非常感谢!

1 个答案:

答案 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更有优势,而不是订户方法的优势。