2011-06-15 94 views
6

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

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

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

那么,类似情况下事件的缺点是什么?我是否也应该遵循这种模式?为了澄清,我应该选择哪一种?我应该什么时候比较喜欢一个?

public event EventHandler Finished; 

// or 

public IDisposable OnFinished(Action continuation) 

非常感谢!

+0

@Jon Skeet:谢谢,我没有注意到我的天使托架需要一些逃脱。 – ShdNx 2011-06-15 10:35:35

+0

UI事件等可以使用UI消息队列发布,并且与使用委托或简单任务相比,可能会非常缓慢/沉重。 – CodingBarfield 2011-06-15 10:54:38

+0

@Barfieldmv:可以使用与Invoke/BeginInvoke相同的技术将动作调用发布到UI线程。这不是区别。 – 2011-06-15 10:59:54

回答

2

我想使用订阅者方法的一个好处是你有能力轻松指定你的委托将被执行的线程。请参阅CancellationToken.Register()的this overload

Upd:嗯,实际上你可以指定你的委托将被发布到的同步上下文。

你是对的趋势。 This article在MSDN Magazine中声明如下:

新组件不应该使用基于事件的异步模式 。该 的Visual Studio异步社区 技术预览版(CTP)包括 文档描述基于任务的 异步模式,其中 组件返回任务和 任务对象,而不是通过 的SynchronizationContext引发事件。基于任务的 API是用.NET编程的异步 的未来。

和制品指document

发起并在TAP的 异步操作的完成是由一个单一的方法来表示 ,和 因此仅存在一个方法来命名。 这是与其中BeginMethodName和 EndMethodName方法是必需的, 和在对比的基于事件的 异步模式,或EAP,其中在 另外需要 MethodNameAsync的 IAsyncResult的图案,或APM图案, 到一个或多个事件,事件 处理程序委托类型和 EventArg派生类型。

事实上,照顾一件事物而不是许多事物是很好的。但是这比TAP优于EAP,而不是订户方法的优势。

+0

这很有道理。方法(订户方法)比事件更灵活,并且问题也更少(例如事件相关的内存泄漏)。另一方面,方法感觉像是退步,因为程序员还必须实现一个存储回调的列表,担心回调列表的线程安全性。所以看起来总的来说,事件比普通的_subscriber_方法更好(这里没有谈论EAP),订户方法通常不值得(例如,当指定特殊的回调行为时)。感谢你的回答! – ShdNx 2011-06-17 11:33:29