这个模式叫什么?软锁定?

3

这是一些我有时不得不编写的代码,主要与UI相关,并且总是涉及可能无意中陷入无限循环的事件。

  public class MyClass
  {
    public event EventHandler MyEvent;
    private bool IsHandlingEvent = false;

    public MyClass()
    {
      MyEvent += new EventHandler(MyClass_MyEvent);
    }

    void MyClass_MyEvent(object sender, EventArgs e)
    {
      if (IsHandlingEvent) { return; }

      IsHandlingEvent = true;
      {
        // Code goes here that handles the event, possibly invoking 'MyEvent' again.
        // IsHandlingEvent flag is used to avoid redundant processing.  What is this
        // technique, or pattern called.
        // ...
      }
      IsHandlingEvent = false;
    }
  }

如您所见,使用“IsHandlingEvent”标志可防止冗余或可能无限的事件调用。虽然我并不总是这样做(因为存在明显的危险),但有时它是一个有用的解决方案,但我不知道该如何称呼它。缺乏更好的术语,我一直在使用“软锁”。真正的名称是什么?
编辑: 是的,我知道它不是线程安全的等等。这是一个命名问题,而不是设计问题。但既然值得讨论… 代码改进:比此模式更好的替代方案?

6
请注意,这段代码不是线程安全的。在一个线程测试完 IsEventHandling 后,可能会立即发生上下文切换。但如果是与用户界面相关的代码,则可能没问题,因为它将是用户界面线程引发事件。 - dlev
8
它也不具备异常安全性。因此,我认为这种模式应该被称为“不要使用” :-) - Corey Kosak
3
如果在单个线程上它是可重入的,它也会表现不正确;使用计数器可能效果更好。 - Marc Gravell
1
@Marc Gravell,我认为他特别想防止这段代码被重入。正如您所看到的,使用标志“IsHandlingEvent”可防止冗余或可能无限的事件调用。 - Scott Chamberlain
4
回滚到第一版。如果你想建议更好的实现方式,请回答问题,不要编辑原始贴(OP)的代码,因为问题、评论和其他答案将不再有意义。 - Clement Herreman
显示剩余9条评论
2个回答

3

关于设计方面已经有很多讨论(不具备线程安全等)。

你似乎在询问一个名称……我不知道这是否普遍,但我听过它被称为可重入哨兵。


3
感谢您坚持主题。 - A.R.

1

我认为这与信号量有些关联,即:使用布尔变量来查看对某个东西的访问。

编辑:正如问题评论中指出的那样,应该避免使用这种“模式”,因为它不是线程安全、异常安全和好的。


4
就我个人而言,我认为这跟信号量完全不同。信号量是一种实际的同步原语,而另一种只是布尔值和祷告。 - Adam Houldsworth
我并没有说它是一个原始的信号量(semaphore),但它看起来更像是这种类型的。 - Clement Herreman
我知道你没有说它是一个信号量,我只是认为它在使用上甚至不像一个。 - Adam Houldsworth
@Adam:你为什么这样认为呢?(真的很好奇) - Clement Herreman
我想原始代码版本在递增和递减资源计数方面的结构可能相似。作为答案,我认为信号量参考有点牵强,而信号量在技术上并不是一种模式。 - Adam Houldsworth
一个信号量会暂停执行,直到可以继续进行为止 - 就像锁一样。保护区域的执行最终应该发生。而这个解决方案只是简单地将事件丢弃在地面上,并假装什么也没有发生。 - viraptor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接