事件始终为空,因此无法处理

时间:2019-01-17 04:56:37

标签: c# class event-handling

我有3个类,一个类触发事件,另一个类调用事件处理程序发送者,最后一个接收事件。但是,发送方类中的事件处理程序始终为null,因此接收方从不处理事件。我无法确定为什么是null,因为我将其指定为StartEventHandler,如下所示。

我试图输入调试语句以查看为什么从未运行该处理程序,并发现它从未进入C类。

头等舱触发事件:

Class A {
    public void Button_Click(object sender, RoutedEventArgs e)
    {            
        B senders = new B();
        senders.OnPageSwap(new StartEventArgs());
    }
}

第二类是发件人

public delegate void StartEventHandler(object sender, StartEventArgs e);
public class B
{
    public event StartEventHandler PageSwap;
    public virtual void OnPageSwap(StartEventArgs e)
    {
        Console.WriteLine("Entered PageSwapSender");
        if(PageSwap != null) PageSwap(this, e);
    }
}

第三类是接收者

Class C {
    B sender = new B();

    void Connect()
    {
        sender.PageSwap += new StartEventHandler(this.sender_PageSwap);
        Console.WriteLine("Entered Connect");
    }

    private void sender_PageSwap(object sender, StartEventArgs e)
    {
        Console.WriteLine("Entered Handler");
    }
}

谁能告诉我为什么PageSwap中的class B总是null从而从不运行PageSwap(this, e)

3 个答案:

答案 0 :(得分:0)

C.Connect()没有被调用,而是需要被调用,因为这是您注册调用this.sender_PageSwap的EventHandler的地方。没有那,什么都不会发生。

答案 1 :(得分:0)

  

事件如何进行以及代码存在问题

事件是Delegate的包装,它提供类型安全的访问,而不会破坏委托对象的状态。在您的情况下,class A通过类B中定义的OnPageSwap方法调用启动事件的注册,该调用首先应在类C中执行事件{{ 1}}注册,并且应使用相同的B对象实例,该实例用于调用Connect方法,以便事件注册可以被连接并因此被调用,Connect中不需要PageSwap。实例可以在方法或构造函数中传递。我的示例代码使用new object B方法

  

用简单的话

您没有在Class C中调用Connect(B sender)方法,然后在Connect中注册事件应与Class C相同。事件设计也是不正确的,因为它不是线程安全的,并且对象可能会损坏。事件应通过访问器公开。

  

以下是该代码的有效版本,包括测试控制台

Connect method
  

修改:

  1. 将Connect方法的定义更改为Class B,以便void Main() { new A().Button_Click(this, new RoutedEventArgs()); } public class A { public void Button_Click(object sender, RoutedEventArgs startEventArgs) { B senders = new B(); senders.OnPageSwap(new StartEventArgs()); } } public delegate void StartEventHandler(object sender, StartEventArgs e); public class B { private event StartEventHandler _PageSwap; private readonly object _lock = new Object(); // Event Access via thread safe accessor public event StartEventHandler PageSwap { add { lock (_lock) { _PageSwap += value; } } remove { lock (_lock) { _PageSwap -= value; } } } public virtual void OnPageSwap(StartEventArgs e) { Console.WriteLine("Entered PageSwapSender"); var c = new C(); c.Connect(this); if (_PageSwap != null) _PageSwap(this, e); } } public class C { public void Connect(B sender) { sender.PageSwap += new StartEventHandler(this.sender_PageSwap); Console.WriteLine("Entered Connect"); } private void sender_PageSwap(object sender, StartEventArgs e) { Console.WriteLine("Entered Handler"); } } public class StartEventArgs : EventArgs { } 接收B类的相同对象,该对象正在public void Connect(B sender)的{​​{1}}内部调用Connect方法
  2. 创建了class C作为占位符,可以用实际代码代替
  3. 提供了一个测试控制台以测试工作/事件调用
  

结果:

public virtual void OnPageSwap(StartEventArgs e)
  

编辑1:

除了对事件的不正确访问(未使用同一对象)之外,事件的设计还有缺陷,它需要通过线程安全访问器公开,请考虑最新的代码修改,其中PageSwap事件通过线程安全包装器公开

答案 2 :(得分:0)

代码的问题在于,您要实例化类B的两个单独实例。在A中,您尝试在B的一个实例上引发事件。在C中,您尝试使用B 的另一个实例来处理引发的事件。

似乎您已经尝试通过在Connect中创建C方法来做正确的事情,但这应该是您传递了B现有实例的地方到C

如果您这样编写代码,那就可以了:

class A
{   
    public void Button_Click(object sender, RoutedEventArgs e)
    {
        B senders = new B();
        C c = new C();
        c.Connect(senders);
        senders.OnPageSwap(new StartEventArgs());
    }
}

public delegate void StartEventHandler(object sender, StartEventArgs e);
public class B
{
    public event StartEventHandler PageSwap;
    public virtual void OnPageSwap(StartEventArgs e)
    {
        Console.WriteLine("Entered PageSwapSender");
        if (PageSwap != null) PageSwap(this, e);
    }
}

class C
{
    public void Connect(B sender)
    {
        sender.PageSwap += new StartEventHandler(this.sender_PageSwap);
        Console.WriteLine("Entered Connect");
    }

    private void sender_PageSwap(object sender, StartEventArgs e)
    {
        Console.WriteLine("Entered Handler");
    }
}