【问题标题】:Mutli-threaded synchronization AND UI thread synchronization. Can it be done?多线程同步和 UI 线程同步。可以做到吗?
【发布时间】:2016-07-05 17:05:14
【问题描述】:

我正在制作一个允许访问系统范围共享资源的库,并希望在其上设置一个类似互斥锁的锁。我过去曾使用Mutex 类来同步不同线程或进程中的操作。

在 UI 应用程序中可能会出现问题。我正在制作的库用于多种产品,其中一些是位于同一主机 UI 应用程序中的插件。因此,库的每个实例的 UI 线程都是相同的 - 因此mutex.WaitOne() 将返回 true,即使资源已被访问。

“资源”是用户的注意力。无论哪个主机进程想要打开它,我都不想打开一个以上的特定子窗口。此外,它可能是另一个线程知道何时可以释放互斥锁(子窗口关闭)。

有没有我可以应用的类或模式,可以让我轻松解决这个问题?

总结我的意图,这可能是理想的虚构类:

var specialMutex = new SpecialMutex("UserToastNotification");
specialMutex.WaitOne(0); // Returns true only once, even on the same thread,
                         // and is respected across different processes.
specialMutex.Release();  // Can be called from threads other than the one
                         // that called WaitOne();

是的,Release 看起来很危险,但它只被资源调用。

【问题讨论】:

  • 所以使用初始值为 1 的Semaphore
  • 很难理解为什么 bool 不能解决这个问题。在 UI 线程上调用 WaitOne() 是非常邪恶的,永远不要那样做。您最好注意一个非常不同的错误生成器,您所描述的只有在您的代码可重入时才会发生。可能有人在调用 DoEvents(),确保不是你。或者有人在调用 WaitOne(),那也可以。
  • @HansPassant:bool 跨进程?请详细说明。
  • 一个在自己的进程中运行的插件?不太可能。
  • @HansPassant 抱歉不清楚:插件不是唯一的消费者。该库的其他实例在独立桌面应用程序中运行。

标签: c# multithreading thread-safety mutex


【解决方案1】:

我认为您想要一个初始值为 1 的 Semaphore。无论线程如何,对 Semaphore 的任何对 WaitOne() 的调用都会尝试减少计数。任何对Release 的调用,无论调用它的线程是什么,都会导致计数递增。

所以如果单个线程初始化一个值为1的信号量,然后调用WaitOne,计数将变为0。如果同一个线程在同一个信号量上再次调用WaitOne,线程将锁定等待发布。

其他线程可能会出现并调用Release 来增加计数。

因此,虽然SemaphoreMutex完全一样,但它可能足够相似,可以让您的程序运行。

【讨论】:

  • 信号量在我脑海中闪过,但我认为它们具有“相同的线程释放”行为。非常感谢!
  • 投反对票?否决票有什么特别的原因吗?提供评论是惯例。
【解决方案2】:

您可以使用比较/交换操作来完成此操作。像这样的:

class Lock {
  int locked = 0;
  bool Enter() { return Interlocked.CompareExchange(ref locked, 1, 0) == 0; }
  void Leave() { Interlocked.CompareExchange(ref locked, 0, 1); }
}

这里,无论从哪个线程调用,Enter 只会返回一次 true,直到你调用 leave。

【讨论】:

  • 很难实现跨进程。
  • 糟糕。错过了那里的多进程部分。
猜你喜欢
  • 1970-01-01
  • 2015-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
相关资源
最近更新 更多