Абонентский метод против события - PullRequest
6 голосов
/ 15 июня 2011

Я заметил новую тенденцию в .NET 4.0, особенно в потенциально многопоточных сценариях, которая позволяет избегать событий и вместо этого предоставлять методы подписчика.

Например, System.Threading.Tasks.Task и Task<TResult> имеют методы ContinueWith () вместо события Completed или Finished.Другим примером является System.Threading.CancellationToken : у него есть метод Register () вместо события CancellationRequested.

Хотя Task.ContinueWith () логичен, поскольку ондопускает простое объединение задач (было бы не так уж и элегантно с событиями), и что оно также позволяет Task<TResult> наследовать от Task (потому что таким образом, Task<TResult> может обеспечить соответствующие перегрузки, которые были бы невозможны для события: если у вас есть событие EventHandler Finished в Task, все, что вы можете сделать, это создать еще одно событие, скажем, событие EventHandler<TaskResultEventArgs> Finished in Task<TResult>, что не очень приятно), но я не могу найтито же самое объяснение для CancellationToken.Register ().

Итак, каковы недостатки событий в подобных сценариях?Должен ли я также следовать этой схеме?Чтобы уточнить, какой из следующих я должен выбрать?Когда я должен предпочесть одно другому?

public event EventHandler Finished;

// or

public IDisposable OnFinished(Action continuation)

Большое спасибо!

1 Ответ

2 голосов
/ 16 июня 2011

Полагаю, одним из преимуществ использования методов подписчика является то, что у вас есть возможность легко указать поток, в котором будет выполняться ваш делегат. См. эту перегрузку из CancellationToken.Register ().

Upd: На самом деле вы можете указать контекст синхронизации, в который будет публиковаться ваш делегат.

Вы правы в отношении тенденции. Эта статья в журнале MSDN гласит следующее:

Новые компоненты не должны использовать основанный на событиях асинхронный образец. Visual Studio асинхронное сообщество Технология Preview (CTP) включает в себя документ, описывающий задачи на основе асинхронный шаблон, в котором компоненты возвращают Task и Объекты задачи вместо поднимая события через SynchronizationContext. На основе задач API - это будущее асинхронных программирование в .NET.

И документ , на который ссылается статья, гласит

Начало и завершение асинхронная операция в TAP представлены одним методом, и таким образом, есть только один метод для имени. Это в отличие от Шаблон IAsyncResult или шаблон APM, где BeginMethodName и Методы EndMethodName являются обязательными, и в отличие от событийного асинхронный шаблон, или EAP, где MethodNameAsync требуется в дополнение к одному или нескольким событиям, событие типы делегатов обработчиков и Типы, полученные из EventArg

И действительно, заботиться об одной вещи вместо многих - это хорошо. Но это скорее преимущество TAP перед EAP, а не преимущество методов подписчика.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...