让我感到困惑的东西,但从来没有引起任何问题......推荐的事件发送方式如下:
public event EventHandler SomeEvent;
...
{
....
if(SomeEvent!=null)SomeEvent();
}
Run Code Online (Sandbox Code Playgroud)
在多线程环境中,此代码如何保证另一个线程不会更改SomeEvent检查null和事件调用之间的调用列表?
更新:为了所有阅读本文的人的利益,自.NET 4起,由于自动生成事件同步的变化,锁定是不必要的,所以我现在就使用它:
public static void Raise<T>(this EventHandler<T> handler, object sender, T e) where T : EventArgs
{
if (handler != null)
{
handler(sender, e);
}
}
Run Code Online (Sandbox Code Playgroud)
并提出它:
SomeEvent.Raise(this, new FooEventArgs());
Run Code Online (Sandbox Code Playgroud)
在阅读过Jon Skeet 关于多线程的文章之后,我试图将他提倡的方法封装在像这样的扩展方法中引发事件(使用类似的通用版本):
public static void Raise(this EventHandler handler, object @lock, object sender, EventArgs e)
{
EventHandler handlerCopy;
lock (@lock)
{
handlerCopy = handler;
}
if (handlerCopy != null)
{
handlerCopy(sender, e);
}
}
Run Code Online (Sandbox Code Playgroud)
然后可以这样调用:
protected virtual void OnSomeEvent(EventArgs e)
{
this.someEvent.Raise(this.eventLock, this, e);
}
Run Code Online (Sandbox Code Playgroud)
这样做有什么问题吗? …
这两个样本是否相同?可以用Invoke和null传播替换旧式的提升吗?
旧:
public event EventHandler<MyEventArgs> MyEvent;
protected virtual void OnMyEvent(MyEventArgs args)
{
EventHandler<MyEventArgs> handler = this.MyEvent;
if (handler != null)
handler(this, args);
}
Run Code Online (Sandbox Code Playgroud)
新:
public event EventHandler<MyEventArgs> MyEvent;
protected virtual void OnMyEvent(MyEventArgs args)
{
this.MyEvent?.Invoke(this, args);
}
Run Code Online (Sandbox Code Playgroud)
空检查很重要但很明显.什么是附加变量?
null-propogation如何在内部工作?它是否对事件有线程安全性?
PS关于事件中的线程安全,您可以在此处阅读:
C#事件和线程安全