我如何在C#中创建一个系统互斥 [英] How can I create a System Mutex in C#
问题描述
我怎样才能创建一个系统/多进程互斥,统筹使用相同的非托管资源的多个进程
背景:
我已经写了使用一个文件打印机,它只能由一个进程时使用的过程。如果我想使用它的计算机上运行多个程序,我需要一种方法来跨系统同步此。
您可以使用System.Threading.Mutex类,它有一个OpenExisting方法来打开一个名为系统互斥体。
块引用>
这不回答这个问题:
我怎样才能创建一个系统/多进程互斥
块引用>
要建立一个全系统的互斥体,调用System.Threading.Mutex构造函数的字符串作为参数。这也被称为一个命名为互斥。要查看它是否存在,我似乎无法找到一个更优美的方法不是试图捕捉:
System.Threading.Mutex _mutey = NULL;
试
{
_mutey = System.Threading.Mutex.OpenExisting(mutex_name);
//我们得到了Mutey,可以尝试获得由WaitOne的
_mutey.WaitOne锁();
}
抓
{
//指定的互斥体不存在,我们应该创建
_mutey =新System.Threading.Mutex(mutex_name) ; //这些名称需要匹配。
}
现在,要成为一个优秀的程序员,你需要,当你结束程序,释放此互斥锁
_mutey.ReleaseMutex();
或者,你可以让它在这种情况下它会被称为抛弃当你的线程退出,并允许另一个进程创建它。
作为一个方面说明的最后一句话描述了被放弃互斥体,当另一个线程获取该互斥锁,异常
System.Threading.AbandonedMutexException
将被抛出告诉他这是在被遗弃的状态中。
我不知道为什么我几年这种方式以前回答过的问题;有(并且是)一个构造函数重载是在检查现有的互斥体要好得多。事实上,我把代码似乎有一个竞争条件! (和可耻的是大家没有纠正我:-P!)
这里的比赛条件:想象两个进程,它们都试图在同一打开现有互斥时间,并且两个得到的代码的捕获部分。然后,其中一个进程创建互斥量,从此幸福地生活。其他进程,但是,尝试创建互斥体,但是这一次,它已经创造!这种检查/互斥的创造必须是原子的。
的 http://msdn.microsoft.com/en-us/library/bwe34f1k(v = VS.90)的.aspx
所以...
VAR requestInitialOwnership = FALSE;
布尔mutexWasCreated;
互斥M =新的Mutex(requestInitialOwnership,
MyMutex,出mutexWasCreated);
我觉得这里的技巧是,看来,你有你实际上并不有一个选项(看起来像一个设计缺陷给我)。有时你,如果你拥有互斥如果你发送
真正
为requestInitialOwnership
也说不清。如果你通过真正
,看来,你调用创建互斥量,那么很明显你拥有它(通过文件证实)。如果你通过真正
,您的电话没有创建互斥量,所有你知道的是,互斥锁已创建的,你不知道,如果其他进程或线程这或许创建互斥体目前拥有互斥锁。所以,你必须的WaitOne
,以确保你有它。但随后,有多少发布
就做你做什么?如果一些其他进程拥有互斥体,当你得到它,那么只有你对的WaitOne
显式调用必须发布
D 。如果你对构造函数调用使你拥有互斥的,你叫的WaitOne
明确,你需要两个发布
取值
我把这些话转换成代码:
VAR requestInitialOwnership = TRUE; / *这似乎是一个错误* /
布尔mutexWasCreated。
互斥M =新的Mutex(requestInitialOwnership,
MyMutex,出mutexWasCreated);
如果(mutexWasCreated!)
{
布尔calledWaitOne = FALSE;
如果/ *我不知道这样的* /
{
calledWaitOne = true的方法(iOwnMutex(米)!);
m.WaitOne();
}
doWorkWhileHoldingMutex();
m.Release();
如果(calledWaitOne)
{
m.Release();
}
}
由于我没有看到一个方法来测试是否您当前拥有互斥体,我会强烈建议你通过
假
来构造,让你知道,你没有自己的互斥,你知道多少次叫发布
。How can I create a system/multiprocess Mutex to co-ordinate multiple processes using the same unmanaged resource.
Background: I've written a procedure that uses a File printer, which can only be used by one process at a time. If I wanted to use it on multiple programs running on the computer, I'd need a way to synchronize this across the system.
解决方案You can use the System.Threading.Mutex class, which has an OpenExisting method to open a named system mutex.
That doesn't answer the question:
How can I create a system/multiprocess Mutex
To create a system-wide mutex, call the System.Threading.Mutex constructor that takes a string as an argument. This is also known as a 'named' mutex. To see if it exists, I can't seem to find a more graceful method than 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. }
Now, to be a good programmer, you need to, when you end the program, release this mutex
_mutey.ReleaseMutex();
or, you can leave it in which case it will be called 'abandoned' when your thread exits, and will allow another process to create it.
[EDIT]
As a side note to the last sentence describing the mutex that is abandoned, when another thread acquires the mutex, the exception
System.Threading.AbandonedMutexException
will be thrown telling him it was found in the abandoned state.[EDIT TWO]
I'm not sure why I answered the question that way years ago; there is (and was) a constructor overload that is much better at checking for an existing mutex. In fact, the code I gave seems to have a race condition! (And shame on you all for not correcting me! :-P )
Here's the race condition: Imagine two processes, they both try to open the existing mutex at the same time, and both get to the catch section of code. Then, one of the processes creates the mutex and lives happily ever after. The other process, however, tries to create the mutex, but this time it's already created! This checking/creating of a mutex needs to be atomic.
http://msdn.microsoft.com/en-us/library/bwe34f1k(v=vs.90).aspx
So...
var requestInitialOwnership = false; bool mutexWasCreated; Mutex m = new Mutex(requestInitialOwnership, "MyMutex", out mutexWasCreated);
I think the trick here is that it appears that you have an option that you don't actually have (looks like a design flaw to me). You sometimes can't tell if you own the mutex if you send
true
forrequestInitialOwnership
. If you passtrue
and it appears that your call created the mutex, then obviously you own it (confirmed by documentation). If you passtrue
and your call did not create the mutex, all you know is that the mutex was already created, you don't know if some other process or thread which perhaps created the mutex currently owns the mutex. So, you have toWaitOne
to make sure you have it. But then, how manyRelease
s do you do? If some other process owned the mutex when you got it, then only your explicit call toWaitOne
needs to beRelease
d. If your call to the constructor caused you to own the mutex, and you calledWaitOne
explicitly, you'll need twoRelease
s.I'll put these words into code:
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(); } }
Since I don't see a way to test whether you currently own the mutex, I will strongly recommend that you pass
false
to the constructor so that you know that you don't own the mutex, and you know how many times to callRelease
.这篇关于我如何在C#中创建一个系统互斥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!