我有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)
。
答案 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
修改:
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方法class C
作为占位符,可以用实际代码代替结果:
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");
}
}