C# 确保只有一个委托与事件关联?

C# 确保只有一个委托与事件关联?,c#,events,C#,Events,我正在连接到进程的退出事件。我为该事件的进程设置了一个复选框,用于确定运行退出的事件时会发生什么。如果在进程运行时选中复选框,它将获取进程并添加退出的事件。如果进程未运行,它将启动进程并添加已退出的事件。如果复选框未选中,则无论进程是否正在运行,我都不执行任何操作 我的问题是,如果进程正在运行,并且我选中了“它将获得一个事件”框,取消选中“设计不发生任何事情”框,然后重新选中该框,那么进程将获得两个完全相同的退出事件。如果我有流程对象,如果已经有一个退出的事件,我怎么能不添加它呢?使用-=运算符

我正在连接到进程的退出事件。我为该事件的进程设置了一个复选框,用于确定运行退出的事件时会发生什么。如果在进程运行时选中复选框,它将获取进程并添加退出的事件。如果进程未运行,它将启动进程并添加已退出的事件。如果复选框未选中,则无论进程是否正在运行,我都不执行任何操作


我的问题是,如果进程正在运行,并且我选中了“它将获得一个事件”框,取消选中“设计不发生任何事情”框,然后重新选中该框,那么进程将获得两个完全相同的退出事件。如果我有流程对象,如果已经有一个退出的事件,我怎么能不添加它呢?

使用-=运算符将事件与委托分离

就像将事件绑定到委托时一样:

EventHandler foo = new EventHandler(this._onClick)
myButton.Click += foo;
如果您将该引用保留在某个位置,也可以这样做:

myButton.Click -= foo;
然后当事件被触发时,它不再调用foo

当复选框被选中时,您可能正在执行的操作如下:

foo.Exited += new EventHandler(your_method);
这样,每次选中该框时,都会得到一个绑定到事件的新处理程序。只使用一个处理程序。这样,当复选框被取消选中时,您可以-=之前与退出事件关联的委托


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

使用-=运算符将事件与委托分离

就像将事件绑定到委托时一样:

EventHandler foo = new EventHandler(this._onClick)
myButton.Click += foo;
如果您将该引用保留在某个位置,也可以这样做:

myButton.Click -= foo;
然后当事件被触发时,它不再调用foo

当复选框被选中时,您可能正在执行的操作如下:

foo.Exited += new EventHandler(your_method);
这样,每次选中该框时,都会得到一个绑定到事件的新处理程序。只使用一个处理程序。这样,当复选框被取消选中时,您可以-=之前与退出事件关联的委托


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

要获取订阅邀请的所有代理的数组,只需使用GetInvoactionList方法。从那里,您可以检查它的长度,或者对它进行迭代,以检查事件将调用多少/哪些委托

 Delegate[] delegates = MyEvent.GetInvocationList();
根据你实际想做的事情,你似乎可以做这样的事情

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


要获取订阅邀请的所有代理的数组,只需使用GetInvoactionList方法。从那里,您可以检查它的长度,或者对它进行迭代,以检查事件将调用多少/哪些委托

 Delegate[] delegates = MyEvent.GetInvocationList();
根据你实际想做的事情,你似乎可以做这样的事情

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


根据这篇Microsoft论坛帖子,您可以在重新分配之前删除现有的处理程序

根据此Microsoft论坛帖子,您只需删除现有处理程序,然后再重新分配它

试试这个:

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--;
            }
        }
    }
}
试试这个:

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

如果必须观察事件,可以使用反射:

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

如果必须观察事件,可以使用反射:

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

您是否可以发布有关如何注册已退出事件的事件处理程序的相关代码?您可能需要查看委托以确定注册了多少个处理程序。也许您可以只注册一次,然后在函数内部根据复选框的当前值确定是否运行?听起来您需要一个已注册的标志,或者使用委托而不是事件。一个委托一次只能分配一个方法。当您新建Process class对象而不是其他对象时,立即注册事件。Process.Exited-=myEventHandler;process.Exited+=myEventHandler;您是否可以发布有关如何注册已退出事件的事件处理程序的相关代码?您可能需要查看委托以确定注册了多少个处理程序。也许您可以只注册一次,然后在函数内部根据复选框的当前值确定是否运行?听起来您需要一个已注册的标志,或者使用委托而不是事件。一个委托一次只能分配一个方法。当您新建Process class对象而不是其他对象时,立即注册事件。Process.Exited-=myEventHandler;process.Exited+=myEventHandler;当复选框未选中时,事件仍应显示
与之相关。当复选框被重新选中时,我希望不注册第二个EventHandler。@Corey然后在类级别添加一个布尔值,指示事件已被分配。如果已设置,则不要再次分配。当复选框未选中时,事件仍应绑定到该复选框。当复选框被重新选中时,我希望不注册第二个EventHandler。@Corey然后在类级别添加一个布尔值,指示事件已被分配。如果已设置,请不要再次分配。这不是我的事件。我无法访问进程的退出调用列表。这不是我的事件。我无法访问进程的已退出调用列表。我确实喜欢这种方法,但在.Net库中使用类型反射似乎有点不妥。不过,与其他答案相比,这似乎是可行的。@Corey只是在subscribe+=之前的一行中取消订阅-=而已。如果您取消订阅之前未订阅的活动,它将不会引发任何问题。我确实喜欢这种方法,但在.Net库中使用类型反射似乎有点不妥。不过,与其他答案相比,这似乎是可行的。@Corey只是在subscribe+=之前的一行中取消订阅-=而已。如果您取消订阅之前未订阅的活动,它将不会抛出。