Reputation: 3213
I have noticed a new tendency in .NET 4.0, specifically in potentially multi-threaded scenarios, which is avoiding events, and providing subscriber methods instead.
For example, System.Threading.Tasks.Task and Task<TResult>
have ContinueWith() methods instead of a Completed or Finished event. Another example is System.Threading.CancellationToken: it has a Register() method instead of a CancellationRequested event.
While Task.ContinueWith() is logical because it allows for easy task chaining (would not be so elegant with events), and that it also allows Task<TResult>
to inherit from Task
(because this way, Task<TResult>
can provide appropriate overloads, which would not be possible for an event: if you have an event EventHandler Finished in Task, all you can do is create another event, say, event EventHandler<TaskResultEventArgs>
Finished in Task<TResult>
, which is not very nice), but I cannot find the same explanation for CancellationToken.Register().
So, what are the disadvantages of events in similar scenarios? Should I also follow this pattern? To clarify, which one of the below should I choose? When should I prefer one against the other?
public event EventHandler Finished;
// or
public IDisposable OnFinished(Action continuation)
Thank you very much!
Upvotes: 6
Views: 524
Reputation: 6556
I guess one advantage of using subscriber methods is that you have the ability to easily specify the thread your delegate will be executed on. See this overload of CancellationToken.Register().
Upd: Well, actually you can specify the synchronization context your delegate will be posted to.
You are right about the tendency. This article in MSDN Magazine states the following:
New components shouldn’t use the event-based asynchronous pattern. The Visual Studio asynchronous Community Technology Preview (CTP) includes a document describing the task-based asynchronous pattern, in which components return Task and Task objects instead of raising events through SynchronizationContext. Task-based APIs are the future of asynchronous programming in .NET.
And the document the article refers to says
Initiation and completion of an asynchronous operation in the TAP are represented by a single method, and thus there is only one method to name. This is in contrast to the IAsyncResult pattern, or APM pattern, where BeginMethodName and EndMethodName methods are required, and in contrast to the event-based asynchronous pattern, or EAP, where a MethodNameAsync is required in addition to one or more events, event handler delegate types, and EventArg-derived types.
And indeed, taking care of one thing instead of many is kind of good. But this is more of advantage of TAP over EAP, not the advantage of subscriber methods.
Upvotes: 2