gpt4 book ai didi

c# - 如何在 C# 中创建系统互斥量

转载 作者:可可西里 更新时间:2023-11-01 07:51:27 26 4
gpt4 key购买 nike

如何创建系统/多进程互斥体来协调使用相同非托管资源的多个进程。

背景: 我写了一个使用文件打印机的程序,一次只能由一个进程使用。如果我想在计算机上运行的多个程序上使用它,我需要一种跨系统同步的方法。

最佳答案

You can use the System.Threading.Mutex class, which has an OpenExisting method to open a named system mutex.

这没有回答问题:

How can I create a system/multiprocess Mutex

要创建系统范围的互斥量,请调用以字符串作为参数的 System.Threading.Mutex 构造函数。这也称为“命名”互斥体。要查看它是否存在,我似乎找不到比 try catch 更优雅的方法了:

System.Threading.Mutex _mutey = null;
try
{
_mutey = System.Threading.Mutex.OpenExisting("mutex_name");
//we got Mutey and can try to obtain a lock by waitone
_mutey.WaitOne();
}
catch
{
//the specified mutex doesn't exist, we should create it
_mutey = new System.Threading.Mutex("mutex_name"); //these names need to match.
}

现在,要成为一名优秀的程序员,您需要在程序结束时释放这个互斥量

_mutey.ReleaseMutex();

或者,您可以保留它,在这种情况下,当您的线程退出时,它将被称为“已放弃”,并允许另一个进程创建它。

[编辑]

作为描述被遗弃的互斥锁的最后一句话的旁注,当另一个线程获取互斥锁时,将抛出异常 System.Threading.AbandonedMutexException 告诉他它在被遗弃的状态。

[编辑两个]

我不确定为什么我在几年前就这样回答了这个问题;有(并且曾经)有一个构造函数重载,它在检查现有互斥量方面要好得多。事实上,我给出的代码似乎存在竞争条件! (你们都因为没有纠正我而感到羞耻!:-P)

这是竞争条件:假设有两个进程,它们都试图同时打开现有的互斥量,并且都到达代码的 catch 部分。然后,其中一个进程创建互斥量并从此过上幸福的生活。然而,另一个进程试图创建互斥量,但这次它已经创建了!这种互斥量的检查/创建需要是原子的。

http://msdn.microsoft.com/en-us/library/bwe34f1k(v=vs.90).aspx

所以...

var requestInitialOwnership = false;
bool mutexWasCreated;
Mutex m = new Mutex(requestInitialOwnership,
"MyMutex", out mutexWasCreated);

我认为这里的诀窍在于,您似乎有一个实际上没有的选项(对我来说看起来像是设计缺陷)。如果您为 requestInitialOwnership 发送 true,有时您无法判断您是否拥有互斥量。如果您传递 true 并且看起来您的调用创建了互斥量,那么显然您拥有它(由文档确认)。如果您传递 true 并且您的调用没有创建互斥量,您所知道的就是互斥量已经创建,您不知道是否有其他进程或线程可能创建了互斥量当前拥有互斥体。因此,您必须 WaitOne 以确保您拥有它。但是,您做了多少 Release?如果在您获得互斥量时其他进程拥有它,则只有您对 WaitOne 的显式调用需要被 Released。如果您对构造函数的调用导致您拥有互斥量,并且您显式调用了 WaitOne,则您将需要两个 Release

我会把这些话写成代码:

var requestInitialOwnership = true; /*This appears to be a mistake.*/
bool mutexWasCreated;
Mutex m = new Mutex(requestInitialOwnership,
"MyMutex", out mutexWasCreated);

if ( !mutexWasCreated )
{
bool calledWaitOne = false;
if ( ! iOwnMutex(m) ) /*I don't know of a method like this*/
{
calledWaitOne = true;
m.WaitOne();
}

doWorkWhileHoldingMutex();

m.Release();
if ( calledWaitOne )
{
m.Release();
}
}

因为我没有找到测试你当前是否拥有互斥量的方法,我强烈建议你将 false 传递给构造函数,这样你就知道你不拥有互斥量,并且您知道要调用多少次 Release

关于c# - 如何在 C# 中创建系统互斥量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2186747/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com