避免在C#中重复的事件订阅

时间:2009-05-03 17:51:01

标签: c# events event-handling delegates

您如何建议避免重复事件订阅的最佳方法?如果这行代码在两个地方执行,则事件将运行两次。我试图避免第三方事件订阅两次。

theOBject.TheEvent += RunMyCode;

在我的委托制定者中,我可以有效地运行这个......

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

但这是最好的方法吗?

5 个答案:

答案 0 :(得分:20)

我认为,最有效的方法是使您的事件成为属性并为其添加并发锁定,如 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; 
        }
    }
}

答案 1 :(得分:5)

我之前已经这样做了......它假设最后一个订阅者被调用是可以接受的。

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);
            }
        }
    }
}

答案 2 :(得分:2)

您的代码是多线程的吗?只有在多线程时才需要并发锁。如果不是它的开销。

因此,您取消订阅和订阅的方法是正确的。

由于

答案 3 :(得分:1)

如果您拥有theObject类的源,那么您可以访问TheEvent的InvocationList。您可以为事件实现自己的添加访问者,并在添加之前进行检查。

但是,我认为你的方法也很好。

答案 4 :(得分:0)

我使用你的方法除了一个细节。我认为,当您创建订阅者或对象的新实例时,应该订阅事件,这使代码更加直接。因此,您需要的只是在正确的物体处理后仔细观察(配置彭定康是方便的解决方案)。

您提到您使用第三方事件,这意味着您无法提供自己的添加/删除方法实现,因为您已被建议。但是在您自己的类中,您应该定义自己的事件添加/删除方法,以解决您的问题。