确保只有一个代表与事件绑定?

时间:2013-05-28 21:09:29

标签: c# events

我正在参加Process的退出活动。我有一个该事件的进程复选框,用于确定运行Exited事件时会发生什么。如果我在Process运行时选中该复选框,它将获取Process并添加Exited事件。如果Process未运行,则启动该过程并添加Exited事件。如果未选中该复选框,无论进程是否正在运行,我都不执行任何操作。

我的问题是,如果进程正在运行并且我选中了框(它获得了一个事件),请取消选中该框(设计没有任何反应),然后重新选中该框,然后该进程将获得两个退出事件(即完全相同的方法)。如果我有Process对象,如果已经有一个Exited事件,我怎么能不添加?

5 个答案:

答案 0 :(得分:2)

根据此Microsoft论坛帖子http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/45071852-3a61-4181-9a25-068a8698b8b6/,您可以在再次分配之前删除现有的处理程序。

答案 1 :(得分:1)

您使用-=运算符将代理与代理分离。

就像你这样做将事件绑定到委托:

EventHandler foo = new EventHandler(this._onClick)
myButton.Click += foo;

如果你在某个地方保留该引用,你也可以这样做:

myButton.Click -= foo;

然后当事件被触发时,它不再调用foo。

当选中复选框时,您可能正在做的事情是这样的:

foo.Exited += new EventHandler(your_method);

这样,每次勾选此框时,都会获得与事件绑定的新处理程序。只使用一个处理程序。这样,当取消选中该复选框时,您可以-=之前与退出事件关联的委托。

编辑,因为你想要的只是保持委托引用的方法不做任何事情,为什么不在检查事件以外的某个点将委托绑定到事件,然后使用方法中的复选框状态来选择是运行方法的其余部分还是以过早返回方式暂停它?

答案 2 :(得分:1)

要获取订阅邀请的所有代表的数组,只需使用GetInvoacationList方法。从那里你可以检查它的长度或迭代它来检查事件将调用多少/哪个代表。

 Delegate[] delegates = MyEvent.GetInvocationList();

根据你实际上要做的事情,似乎你可以做类似的事情;

  if (MyEvent.GetInvocationList().Length > 0)

 if (MyEvent.GetInvoationList().Contains(referenceToMyDelegate))

答案 3 :(得分:0)

试试这个:

delegate void MyDelegate(string message);

class Foo
{
    MyDelegate _delegate = null;
    int _count = 0;

    public event MyDelegate MySingleDelegateEvent
    {
        add
        {
            if (_count == 0)
            {
                _delegate += value;
                _count++;
            }
        }
        remove
        {
            if (_delegate != null)
            {
                _delegate -= value;
                _count--;
            }
        }
    }
}

答案 4 :(得分:0)

如果您必须参与活动,可以使用反射:

class Program
{
    static void Main(string[] args)
    {
        var car = new Car();
        car.Stopped += car_Stopped;
        var evt = car.GetType().GetEvent("Stopped");
        if(evt == null) //evt will be null if nothing is registered to the event
            car.Stopped += car_Stopped;

        car.Stop(); //Prints 'Stopped!' only once

        Console.ReadLine();
    }

    static void car_Stopped(object sender, EventArgs e)
    {
        Console.WriteLine("Stopped!");
    }
}

class Car
{
    public event EventHandler<EventArgs> Stopped;
    protected void OnStopped()
    {
        var temp = Stopped;
        if(temp != null)
            Stopped(this, new EventArgs());
    }
    public void Stop()
    {
        OnStopped();
    }
}