- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 StatusChanged 事件,该事件由我的对象在其状态更改时引发 - 但是,应用程序需要根据新状态执行其他操作。
例如,如果新状态是断开连接,则它必须更新状态栏文本并发送电子邮件通知。
因此,我想创建一个具有可能状态(已连接、已断开连接、接收数据、发送数据等)的枚举,并在事件引发时将其与事件的 EventArgs 参数一起发送(见下文)
定义对象:
class ModemComm
{
public event CommanderEventHandler ModemCommEvent;
public delegate void CommanderEventHandler(object source, ModemCommEventArgs e);
public void Connect()
{
ModemCommEvent(this, new ModemCommEventArgs ModemCommEventArgs.eModemCommEvent.Connected));
}
}
定义新的 EventArgs 参数:
public class ModemCommEventArgs : EventArgs{
public enum eModemCommEvent
{
Idle,
Connected,
Disconnected,
SendingData,
ReceivingData
}
public eModemCommEvent eventType { get; set; }
public string eventMessage { get; set; }
public ModemCommEventArgs(eModemCommEvent eventType, string eventMessage)
{
this.eventMessage = eventMessage;
this.eventType = eventType;
}
}
然后我在应用程序中为事件创建一个处理程序:
ModemComm comm = new ModemComm();
comm.ModemCommEvent += OnModemCommEvent;
和
private void OnModemCommEvent(object source, ModemCommEventArgs e)
{
}
问题是,当对象尝试引发事件时,我收到“对象引用未设置为对象的实例”错误。希望有人能用 n00b 术语解释为什么以及如何修复它:)
最佳答案
当没有客户端订阅事件时,事件为空,因此尝试调用没有订阅者的事件将失败并返回 NullReferenceException。
避免这种情况的一些常用技术:
1) 以线程安全的方式检查 null(从事件引发者的角度来看;客户端上仍然存在竞争条件,但处理该问题是他们的责任)
var handler = this.ModemCommEvent;
if( handler != null ) {
handler(this, new ModemCommEventArgs( ModemCommEventArgs.eModemCommEvent.Connected ));
}
上面的代码是这个的更复杂的版本:
if( this.ModemCommEvent != null ) {
this.ModemCommEvent(this, new ModemCommEventArgs(ModemCommEventArgs.eModemCommEvent.Connected));
}
从事件引发者的角度来看,第一个(创建局部变量)更安全,因为局部变量要么为 null,要么不为 null,并且没有任何改变。然而,在第二个中,在单独线程上运行的客户端可以在检查空值和引发事件之间取消订阅事件。在这种情况下,您将再次遇到 NullReferenceException。如果您和您的代码的客户端都没有在多个线程上执行(没有 BackgroundWorker、Thread 对象、异步调用等),那么更安全的检查是多余的。但是,如果您不确定,那么进入是一个很好的做法。那个,或者做#2。
2) 默认你的事件为空值
public event CommanderEventHandler ModemCommEvent = delegate { };
这通过始终拥有至少一个订阅者来完全回避问题。 “delegate {}”语法创建一个不做任何事情的匿名方法,它是事件的“默认订阅者”。无论有多少客户端订阅或取消订阅您的事件,这个匿名方法将始终存在,防止您的事件为空。
--
这已经在整个互联网上进行了令人作呕的讨论。这是一个这样的例子:
关于使用枚举的 C# 事件处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2578615/
我是一名优秀的程序员,十分优秀!