可以同时从多个线程执行以下代码.
this._sequencer.Completed += OnActivityFinished;
Run Code Online (Sandbox Code Playgroud)
将委托从多个线程添加到事件处理程序是否安全?
从多个线程中删除委托给事件处理程序的线程安全吗?
使这个线程安全的最简单和可维护的方法是什么?
MSDN杂志中的一篇文章讨论了Read Introduction的概念,并给出了一个可以被它破坏的代码示例.
public class ReadIntro {
private Object _obj = new Object();
void PrintObj() {
Object obj = _obj;
if (obj != null) {
Console.WriteLine(obj.ToString()); // May throw a NullReferenceException
}
}
void Uninitialize() {
_obj = null;
}
}
Run Code Online (Sandbox Code Playgroud)
注意这个"可能抛出NullReferenceException"的注释 - 我从来不知道这是可能的.
所以我的问题是:我如何防止阅读介绍?
我还非常感谢编译器决定引入读取的确切解释,因为该文章不包括它.
正如这个问题所示: 使用扩展方法提升C#事件 - 这很糟糕吗?
我正在考虑使用此扩展方法来安全地引发事件:
public static void SafeRaise(this EventHandler handler, object sender, EventArgs e)
{
if (handler != null)
handler(sender, e);
}
Run Code Online (Sandbox Code Playgroud)
但是Mike Rosenblum在Jon Skeet的回答中提出了这个问题:
你们需要将[MethodImpl(MethodImplOptions.NoInlining)]属性添加到这些扩展方法中,否则你可以通过JITter优化将代理复制到临时变量的尝试,从而允许空引用异常.
我在发布模式下做了一些测试,看看当扩展方法没有用NoInlining标记时是否可以获得竞争条件:
int n;
EventHandler myListener = (sender, e) => { n = 1; };
EventHandler myEvent = null;
Thread t1 = new Thread(() =>
{
while (true)
{
//This could cause a NullReferenceException
//In fact it will only cause an exception in:
// debug x86, debug x64 and release x86
//why doesn't it …Run Code Online (Sandbox Code Playgroud) 我有与此MSDN杂志文章相关的问题.
阅读简介正如我刚才所解释的,编译器有时会将多个读取融合为一个.编译器还可以将单个读取拆分为多个读取.在.NET Framework 4.5中,读取介绍比读取消除要少得多,并且仅在非常罕见的特定情况下发生.但是,它有时会发生.
public class ReadIntro {
private Object _obj = new Object();
void PrintObj() {
Object obj = _obj;
if (obj != null) {
Console.WriteLine(obj.ToString());
// May throw a NullReferenceException
}
}
void Uninitialize() {
_obj = null;
}
}
Run Code Online (Sandbox Code Playgroud)
如果检查PrintObj方法,obj.ToString表达式中的obj值看起来永远不会为null.但是,该行代码实际上可能会抛出NullReferenceException.CLR JIT可能会编译PrintObj方法,就好像它是这样编写的:
void PrintObj() {
if (_obj != null) {
Console.WriteLine(_obj.ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
但这不是一个与事件合作的模式吗?!
void RaiseEvent()
{
var myEvent = MyEvent;
if (myEvent != null)
{
myEvent(this, EventArgs.Empty);
}
}
Run Code Online (Sandbox Code Playgroud)
我想念一些重要的东西吗?