相关疑难解决方法(0)

添加委托给事件 - 线程安全

可以同时从多个线程执行以下代码.

this._sequencer.Completed += OnActivityFinished;
Run Code Online (Sandbox Code Playgroud)

将委托从多个线程添加到事件处理程序是否安全?

从多个线程中删除委托给事件处理程序的线程安全吗?

使这个线程安全的最简单和可维护的方法是什么?

c#

28
推荐指数
3
解决办法
7492
查看次数

阅读C#简介 - 如何防范它?

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"的注释 - 我从来不知道这是可能的.

所以我的问题是:我如何防止阅读介绍?

我还非常感谢编译器决定引入读取的确切解释,因为该文章不包括它.

.net c# multithreading

24
推荐指数
2
解决办法
1020
查看次数

方法内联优化能否导致竞争条件?

正如这个问题所示: 使用扩展方法提升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)

.net inline-method race-condition

15
推荐指数
2
解决办法
674
查看次数

事件提升和.net 4.5中的阅读介绍

我有与此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)

我想念一些重要的东西吗?

.net c# events multithreading

2
推荐指数
1
解决办法
874
查看次数