Roy*_*mir 13 .net c# events .net-4.0
使用我的cusom EventArgs,例如:
public event EventHandler<MyEventArgs> SampleEvent;
Run Code Online (Sandbox Code Playgroud)
来自msdn, 例如:
public class HasEvent
{
// Declare an event of delegate type EventHandler of
// MyEventArgs.
public event EventHandler<MyEventArgs> SampleEvent;
public void DemoEvent(string val)
{
// Copy to a temporary variable to be thread-safe.
EventHandler<MyEventArgs> temp = SampleEvent;
if (temp != null)
temp(this, new MyEventArgs(val));
}
}
Run Code Online (Sandbox Code Playgroud)
我有两个问题:
1)查看标记的代码:
我没有看到为什么它应该被复制到另一个参数(关于线程)的原因
因为我们有event
keyowrd,没有人可以触及它的调用列表(我的意思是没有局外代码)
2)如果我没有弄错,该 DemoEvent
函数应该是虚拟的,所以它可以在子类中重写...(我确定我已经在某处看到了它)
奇怪的是,resharper也不会添加虚拟:
所以,如果我有这个代码:
它暗示我:
当我按下它时:
所以我的两个问题:
1)EventHandler<MyEventArgs> temp = SampleEvent;
关于线程安全,这条线将解决的场景是什么 ?
2)功能不应该是virtual
?(我确定我已经看到虚拟的这种模式)
Adr*_*tti 10
这行EventHandler temp = SampleEvent是什么情形; 关于线程安全会解决吗?
想象一下你这样做:
if (SampleEvent != null)
SampleEvent(this, new MyEventArgs());
Run Code Online (Sandbox Code Playgroud)
如果另一个线程将在if之后但在调用之前分离事件处理程序,那么你将尝试调用一个null
委托(并且你会得到一个异常).
该功能不应该是虚拟的吗?(我确定我已经看到虚拟的这种模式)
是的,如果该类不是sealed
那么你应该标记该功能virtual
(它不是强制性的,但它是一个公认的模式).
编辑
Time Thread 1 Thread 2 1 obj.SampleEvent += MyHandler; 2 if (SampleEvent != null) 3 { obj.SampleEvent -= MyHandler; 4 SampleEvent(this, new MyEventArgs()); 5 }
在这种情况下,在时间4你会打电话给一个null
代表,它会抛出一个NullReferenceException
.现在看看这段代码:
Time Thread 1 Thread 2 1 obj.SampleEvent += MyHandler; 2 var sampleEvent = SampleEvent; 3 if (sampleEvent != null) 4 { obj.SampleEvent -= MyHandler; 5 sampleEvent(this, new MyEventArgs()); 6 }
现在在时间5你调用sampleEvent
它并保留旧的内容SampleEvent
,在这种情况下它不会抛出任何异常(但MyHandler
即使它被第二个线程删除它也会调用).
if (SampleEvent != null)
SampleEvent(this, new MyEventArgs(val));
Run Code Online (Sandbox Code Playgroud)
这是一场经典的穿线比赛.在此代码运行时,另一个线程可以取消订阅事件处理程序.这使得if()语句断定存在订阅者,但事件调用因NullReferenceException而失败.将委托对象复制到本地变量可确保通过取消订阅事件处理程序来更改委托对象引用的客户端代码不会导致崩溃.还有一个问题,你会在取消订阅之后调用事件处理程序,但这是一个不可避免的竞争,并不一定像NRE那样致命,并且可以由事件处理程序处理,与NRE不同.
是的,像这样的方法通常被保护为虚拟并命名为OnSampleEvent(),因此派生类可以改变事件引发行为.
归档时间: |
|
查看次数: |
933 次 |
最近记录: |