检查事件处理程序是否为null时,是否基于每个线程完成?
确保有人正在听这个事件就像这样:
EventSeven += new DivBySevenHandler(dbsl.ShowOnScreen);
Run Code Online (Sandbox Code Playgroud)
如果我在上面检查null的模式之后添加代码,那么为什么我需要一个空检查(从这个站点获取的代码).我错过了什么?
此外,事件和GC的规则是什么?
Mar*_*ell 51
问题是如果没有人订阅该事件,它就是null.并且你无法调用null.跳过三种方法:
public event EventHandler MyEvent = delegate {};当空检查,是线程安全的,你必须在理论上首先捕捉委托引用(如果它的检查和调用不同的):
protected virtual void OnMyEvent() {
EventHandler handler = MyEvent;
if(handler != null) handler(this, EventArgs.Empty);
}
Run Code Online (Sandbox Code Playgroud)
扩展方法具有不寻常的属性,它们可以在null实例上调用...
public static void SafeInvoke(this EventHandler handler, object sender)
{
if (handler != null) handler(sender, EventArgs.Empty);
}
public static void SafeInvoke<T>(this EventHandler<T> handler,
object sender, T args) where T : EventArgs
{
if (handler != null) handler(sender, args);
}
Run Code Online (Sandbox Code Playgroud)
然后你可以打电话:
MyEvent.SafeInvoke(this);
Run Code Online (Sandbox Code Playgroud)
并且它是零安全的(通过检查)和线程安全的(通过仅读取一次引用).
Jon*_*eet 48
我真的不清楚你的意思我害怕,但如果委托的可能性为null,你需要在每个线程上单独检查.通常你会这样做:
public void OnSeven()
{
DivBySevenHandler handler = EventSeven;
if (handler != null)
{
handler(...);
}
}
Run Code Online (Sandbox Code Playgroud)
这可以确保即使您EventSeven在课程期间的更改OnSeven()无法获得NullReferenceException.
但是你是对的,如果你肯定有一个订阅的处理程序,你不需要空检查.这可以通过"无操作"处理程序在C#2中轻松完成:
public event DivBySevenHandler EventSeven = delegate {};
Run Code Online (Sandbox Code Playgroud)
另一方面,如果您可以从各种线程获得订阅,您可能需要某种锁定以确保您拥有"最新"处理程序集.我在我的线程教程中有一个例子可以提供帮助 - 尽管我通常建议尽量避免要求它.
在垃圾收集方面,事件发布者最终会引用事件订阅者(即处理程序的目标).如果发布者的寿命比订阅者长,这只是一个问题.
unk*_*656 30
我想附加一些关于C#6.0-Syntax的简短信息:
现在可以替换这个:
var handler = EventSeven;
if (handler != null)
handler.Invoke(this, EventArgs.Empty);
Run Code Online (Sandbox Code Playgroud)
有了这个:
handler?.Invoke(this, EventArgs.Empty);
Run Code Online (Sandbox Code Playgroud)
protected virtual void OnMyEvent()
{
EventHandler handler = MyEvent;
handler?.Invoke(this, EventArgs.Empty);
}
Run Code Online (Sandbox Code Playgroud)
下到单线:
protected virtual void OnMyEvent() => MyEvent?.Invoke(this, EventArgs.Empty);
Run Code Online (Sandbox Code Playgroud)