关于自定义事件的问题
问题描述:
我正在为C#进行自定义事件,有时它不起作用。关于自定义事件的问题
这就是我正在做的事件发生:
private bool isDoorOpen;
public bool IsDoorOpen {
get { return isDoorOpen;}
private set { isDoorOpen = value; DoorsChangeState(this, null);}
}
而这些事件的声明:
//events
public delegate void ChangedEventHandler(Elevator sender, EventArgs e);
public event ChangedEventHandler PositionChanged;
public event ChangedEventHandler DirectionChanged;
public event ChangedEventHandler BreaksChangeState;
public event ChangedEventHandler DoorsChangeState;
因为有连接到事件的方法这种长期工作原理,但如果没有,则会抛出一个空引用异常。我究竟做错了什么?
答
推荐的方法来调用一个事件是
var handler = this.DoorsChangeState;
if (handler != null)
handler(this, null);
之所以本地复制的处理程序是,当你检查空另一个线程柜面事件处理程序的变化。
编辑:发现文章谈论竞赛条件。 http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx
答
如果某个事件在触发时未订阅,则会抛出NullReferenceException。这是正确的行为,而不是你做错了。
您应该检查:
if(DoorsChangeState != null)
{
DoorsChangeState(this, null); // Only fire if subscribed to
}
答
调用之前必须检查,如果事件是空的事件:
if (DoorsChangeState != null)
DoorsChangeState(this, null);
当DoorsChangeState
为空,这意味着有该事件没有侦听。
答
您需要检查事件是否已订阅。
我使用这个标准表格来抛出所有的事件。
var temp = EventName;
if(EventName!= null)
temp(this, null);
答
我知道这个问题已经在SO上多次讨论(和回答)了。
而且这里的某个地方我得到了下面的扩展方法,使这种模式更易于使用:
public static class EventHandlerExtensions
{
public static void FireEvent<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs
{
var temp = handler;
if (temp != null)
{
temp(sender, args);
}
}
public static void FireEvent(this EventHandler handler, object sender)
{
var temp = handler;
if (temp != null)
{
temp(sender, EventArgs.Empty);
}
}
}
因此,在你的代码,你可以说:
public bool IsDoorOpen
{
get { return isDoorOpen;}
private set
{
isDoorOpen = value;
DoorsChangeState.FireEvent(this);
}
}
+0
+1这使得一个非常好的语法! – MPritchard 2010-05-07 07:35:43
+1没有意识到线程安全问题以及事件不可变的事实。感谢您的链接。 – 2010-05-07 07:02:25