Как я могу контролировать порядок запуска обработчиков событий? - PullRequest
19 голосов
/ 05 ноября 2008

Запускаются ли обработчики событий в том порядке, в котором они прикреплены к событию? Если нет, могу ли я установить какой-либо порядок в обработчиках событий, чтобы они вызывались в определенном порядке?

Ответы [ 5 ]

18 голосов
/ 05 ноября 2008

Предполагая простую реализацию события (используя + = и - = в поле делегата, которое, в свою очередь, будет использовать Delegate.Combine/Remove), тогда да, обработчики событий будут вызываться в том порядке, в котором они подписаны. Гарантия фактически предоставляется в документации Delegate.Combine:

Возвращаемое значение

Новый многоадресный (комбинируемый) делегат со списком вызовов, которые объединяет списки вызовов a и b в этом порядке.

См. Мою статью о событиях , где приведены некоторые примеры того, что Delegate.Combine/Remove делает (и какие события происходят под обложками).

4 голосов
/ 17 декабря 2008

Не НЕ полагаться на порядок событий . Все отправки событий должны быть логически независимыми, как если бы они происходили параллельно.

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

Я сделаю еще один шаг и утверждаю, что если вам нужно принять заказ на запуск событий, у вас серьезный недостаток дизайна и / или неправильное использование событий.

2 голосов
/ 05 ноября 2008

Я бы порекомендовал "обернуть его".

Сделай что-нибудь подобное ...

MyObject.MyEvent += new MyEventHandler(Wrapper);

public void Wrapper()
{
    Method1();
    Method3();
    Method2();
}

Таким образом, вы все еще подключаете событие, но имеете полный контроль над тем, что называется.

2 голосов
/ 05 ноября 2008

У вас может быть один обработчик событий, который вызывает другие функции или делегаты в указанном порядке.

0 голосов
/ 08 июля 2009

Извините за поздний ответ.


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

У меня есть форма, и когда я нажимаю кнопку на форме, объект добавляется в коллекцию где-то в моем коде.

В коллекции есть событие "Добавлено", и к нему подключены два делегата. Один из методов удаляет любой элемент, только что добавленный в коллекцию, а другой показывает сообщение пользователю.


Если у меня есть некоторый код, показанный здесь, исключение «IndexOutOfRange» будет генерироваться при запуске события:

// this methods hooks two delegates to MyCollection.Added event, but the order results in a "IndexOutOfRange" exception after the event is triggered
HookEvents()
{
   MyCollection.Added += new CollectionItemAddedHandler(DeleteItem_After_CollectionItemAdded);

   MyCollection.Added += new CollectionItemAddedHandler(ShowMessage_After_CollectionItemAdded);
}


// when user click a button on form, add a object to MyCollection
Button_Clicked()
{
   MyCollection.Add(new object());     
}

// at the moment a object is added into the collection, this method remove it
DeleteItem_After_CollectionItemAdded(NewIndexArgs e)
{
    MyCollection.Remove(e.NewIndex); // e.NewIndex represents the newly added item index in current collection  
}

// at the moment a object is added into the collection, this method show its information (hey, but remember, I just remove it in the previous method)
ShowMessage_After_CollectionItemAdded(NewIndexArgs e)
{
    MessageBox.Show(MyCollection[e.NewIndex]); // tell user what is just added into the current collection
    // a "IndexOutOfRange" exception is thrown here....
}

Что сделает этот сценарий корректным , так это то, что метод «ShowMessage_After_CollectionItemAdded» должен быть запущен first , а затем это будет метод «DeleteItem_After_CollectionAdded».

Хотя сначала мы можем + = метод «ShowMessage ...», иногда мы не можем предопределить эту последовательность до времени выполнения .

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