也许我正在做一些非常错误的事情,但不知怎的,这段代码总是因NullReferenceException而崩溃:
public class IncomingMessageEventData : EventArgs
{
public IncomingMessageEventData(SpecialClasses.IncomingMessageData _msg, List<string> _toreturn)
{
msg = _msg;
ToReturn = _toreturn;
}
public SpecialClasses.IncomingMessageData msg { get; set; }
public List<string> ToReturn { get; set; }
}
public delegate void IncomingMessageHook(IncomingMessageEventData Args);
public event IncomingMessageHook InComingMessage;
public string NewMessage(string[] _message, System.Net.IPEndPoint RemoteIP)
{
if (InComingMessage != null)
{
IncomingMessageEventData data = new IncomingMessageEventData(new SpecialClasses.IncomingMessageData(_message, RemoteIP), new List<string>());
string ToReturn = "";
InComingMessage(data);
foreach (var item in data.ToReturn)
{
if (item.Length > 0)
ToReturn = item;
}
return ToReturn;
}
else return null;
}
有两种方法同时挂钩事件,这可能是原因吗?如果是这样,我该如何避免呢?或者传递一个ref List而不是从钩子方法获取值的方法?
谢谢!
编辑:更新了代码。哪个有效! ......我想我知道我做错了什么。
请参阅该程序,它是使用通过Reflection加载的插件的一部分。在调试之前,我可能有一点点忘记将更新的插件dll复制到插件目录。 ..呵呵。 ^^; 抱歉!但至少我的代码现在使用最佳实践; P非常感谢那个,我会把它标记为答案!
答案 0 :(得分:5)
这里有很多问题。
传递List<T>
作为ref参数不是一个好方法。只需使用该类型上已有的标准List<T>
/ ref
方法,就可以修改out
而不涉及Add
/ Remove
。
您正在使用非标准表单来处理事件处理程序。更常见的是坚持EventHandler<TEventArgs>
,其中TEventArgs
是从EventArgs
派生的某个类。要从事件处理程序来回传递的数据应使用自定义EventArgs
类上的属性或方法进行处理。
您的事件处理程序逻辑不是线程安全的。您需要捕获事件处理程序的本地副本,以便考虑在执行空检查后有人取消订阅的情况。这是典型的模式:
// Capture the handler in a local
EventHandler<MyEventArgs> handler = this.MyEvent;
if (handler != null)
{
// Invoke using the local copy
handler(this, new MyEventArgs(/* ... */));
}