gpt4 book ai didi

使用枚举的 C# 事件处理程序

转载 作者:行者123 更新时间:2023-11-30 13:34:40 25 4
gpt4 key购买 nike

我有一个 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# Events and Thread Safety

关于使用枚举的 C# 事件处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2578615/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com