Я смотрел на Prism EventAggregator и его 'отлично. Больше всего меня беспокоило то, что он способен правильно распределять потоки в потоках пользовательского интерфейса.
Мне было интересно, смогу ли я использовать эту возможность, чтобы предоставить разработчикам модулей класс, который можно использовать для создания потоков аналогично BackgroundWorker. Интерфейс класса может быть несколько похож на
public interface IMyTask
{
event DoWorkEventHandler DoWork;
event RunWorkerCompletedEventHandler RunWorkerCompleted;
void RunTaskAsync(object obj);
}
Для лучшего понимания я сохранил типы, аналогичные фоновому. В реализации я регистрирую события Taskstart и TaskComplete
public class TaskStartEventPayload
{
public SubscriptionToken token { get; set; }
public object Argument { get; set; }
}
public class TaskStartEvent : CompositePresentationEvent<TaskStartEventPayload>
{
}
public class TaskCompleteEventPayload
{
public SubscriptionToken token { get; set; }
public object Argument { get; set; }
public object Result { get; set; }
}
public class TaskCompleteEvent : CompositePresentationEvent<TaskCompleteEventPayload>
{
}
В конструкторе для класса MyTask я беру, какой поток требуется для завершения, как
public MyTask(IEventAggregator eventAggregator, bool isUICompletion)
{
if (eventAggregator == null)
{
throw new ArgumentNullException("eventAggregator");
}
_eventAggregator = eventAggregator;
_eventAggregator.GetEvent<TaskStartEvent>().Subscribe(TaskStartHandler, ThreadOption.BackgroundThread, false, new Predicate<TaskStartEventPayload>(StartTokenFilter));
if(isUICompletion)
_token = _eventAggregator.GetEvent<TaskCompleteEvent>().Subscribe(TaskCompleteHandler, ThreadOption.UIThread,true,new Predicate<TaskCompleteEventPayload>(CompleteTokenFilter));
else
_token = _eventAggregator.GetEvent<TaskCompleteEvent>().Subscribe(TaskCompleteHandler, ThreadOption.BackgroundThread, true, new Predicate<TaskCompleteEventPayload>(CompleteTokenFilter));
}
здесь я регистрируюсь с фильтрами, где функция фильтра возвращает событие, только если у него есть полезный груз, имеющий тот же токен, который был получен при подписке.
далее я использую
public void RunTaskAsync(object obj)
{
//create payload
_eventAggregator.GetEvent<TaskStartEvent>().Publish(payload);
}
public void TaskStartHandler(TaskStartEventPayload t)
{
//fire dowork and create payload
DoWork(this, args);
_eventAggregator.GetEvent<TaskCompleteEvent>().Publish(tc);
}
public void TaskCompleteHandler(TaskCompleteEventPayload t)
{
RunWorkerCompleted(this, args);
}
Этот класс можно использовать как
MyTask et = new MyTaskagg, true);
et.DoWork += new System.ComponentModel.DoWorkEventHandler(et_DoWork);
et.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(et_RunWorkerCompleted);
et.RunTaskAsync("Test");
Преимущество, которое я вижу в этом подходе,
1. Он использует пул потоков, поэтому нет необходимости создавать потоки, как в backgroundWorker.
2. Правильная сортировка потока в случае, если RunWorkerCompleted будет выполняться в потоке пользовательского интерфейса.
Пожалуйста, дайте совет, если было бы правильно использовать Eventaggregator в качестве Threader.