2009-05-03 3 views
17

Как вы можете предложить лучший способ избежать дублирования подписки на события? если эта строка кода выполняется в двух местах, событие будет запускаться дважды. Я стараюсь избегать сторонних событий от подписки дважды.Избегайте дублирования подписки на события в C#

theOBject.TheEvent += RunMyCode; 

В моей делегат сеттера, я могу эффективно управлять этим ...

theOBject.TheEvent -= RunMyCode; 
theOBject.TheEvent += RunMyCode; 

, но это то, что наилучшим образом?

ответ

19

Я думаю, наиболее эффективный способ, чтобы сделать ваше мероприятие свойства и добавить параллелизм замки к ней, как и в этом Example:

private EventHandler _theEvent; 
private object _eventLock = new object(); 
public event EventHandler TheEvent 
{ 
    add 
    { 
     lock (_eventLock) 
     { 
      _theEvent -= value; 
      _theEvent += value; 
     } 
    } 
    remove 
    { 
     lock (_eventLock) 
     { 
      _theEvent -= value; 
     } 
    } 
} 
+2

Дэйв Мортон сменил свой домен. Новый URL-адрес: http://codinglight.blogspot.com/2009/02/preventing-duplicate-subscriptions-to.html –

+0

FYI, если вы получили ссылку 503 по ссылке, просто обновите страницу. Кажется, он загрузился после нескольких попыток для меня. – Dan

1

Если у вас есть источник для класса объекта, у вас есть доступ к InvocationList из TheEvent. Вы можете реализовать свой собственный add accessor для события и проверить перед добавлением.

Однако, я думаю, что ваш подход тоже прекрасен.

2

резьбовых Ваш код мульти? Блокировка параллелизма необходима только при многопоточности. Если это не накладные расходы.

Таким образом, ваш подход к отписке и подписке является правильным.

Thanks

0

Я использую ваш подход, кроме одной детали. Я думаю, что события должны быть подписаны при создании нового экземпляра подписчика или объекта, это делает код более прямым. Таким образом, все, что вам нужно, - это просто внимательно следить за правильным размещением объектов (распоряжаться паттеном это удобное решение для этого).

Вы упомянули, что используете стороннее мероприятие, это означает, что вы не можете предоставить свою собственную реализацию для добавления/удаления методов, как вам было сообщено. Но в ваших собственных классах со своими собственными событиями вы должны определить свою собственную реализацию методов добавления/удаления для события, чтобы решить вашу проблему.

4

Я сделал это раньше .... предполагается, что последним подписчиком является то, что вызвано.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyObject my = new MyObject(); 
      my.Changed += new EventHandler(my_Changed); 
      my.Changed += new EventHandler(my_Changed1); 

      my.Update(); 
      Console.ReadLine(); 
     } 

     static void my_Changed(object sender, EventArgs e) 
     { 
      Console.WriteLine("Hello"); 
     } 
     static void my_Changed1(object sender, EventArgs e) 
     { 
      Console.WriteLine("Hello1"); 
     } 
    } 
    public class MyObject 
    { 
     public MyObject() 
     { 
     } 
     private EventHandler ChangedEventHandler; 
     public event EventHandler Changed 
     { 
      add 
      { 
       ChangedEventHandler = value; 
      } 
      remove 
      { 
       ChangedEventHandler -= value; 
      } 
     } 
     public void Update() 
     { 
      OnChanged(); 
     } 

     private void OnChanged() 
     { 
      if (ChangedEventHandler != null) 
      { 
       ChangedEventHandler(this, null); 
      } 
     } 
    } 
} 
+4

приятный, для тех читателей скорости, которые, возможно, пропустили это, это важная линия. ChangedEventHandler = значение; вместо + =. Отлично подходит для одиночного использования - может быть, для меня в некоторых случаях - спасибо! – ScottCate

Смежные вопросы