跨进程互斥体实例化
Cross-process mutex instantiation
刚刚编写了一个必须一次处理一次的简单程序,因此通过使用具有特定名称的键控 Mutex
来实现。
代码(简化)如下所示。
static readonly string APP_NAME = "MutexSample";
static void Main(string[] args)
{
Mutex mutex;
try
{
mutex = Mutex.OpenExisting(APP_NAME);
// At this point, with no exception,
// the Mutex is acquired, so there is another
// process running
// Environment.Exit(1); or something
}
catch (WaitHandleCannotBeOpenedException)
{
// If we could not acquire any mutex with
// our app name, let's create one
mutex = new Mutex(true, APP_NAME);
}
Console.ReadKey(); // Just for keeping the application up
// At some point, I just want to release
// the mutex
mutex.ReleaseMutex();
}
我的第一次尝试是像 new Mutex(false, APP_NAME)
一样实例化 Mutex
,但是调用 mutex.ReleaseMutex()
时抛出异常
System.ApplicationException: 'Object synchronization method was called from an unsynchronized block of code.'
刚刚注意到构造函数的第一个参数(initiallyOwned
)标记了创建Mutex
的当前线程是否拥有它,不出所料,一个线程不能释放一个Mutex
不属于该线程。
因此将此参数更改为 true
解决了该问题,如上面的代码所示。
嗯,我的问题是,该参数的全部意义是什么?我的意思是,我什么时候需要创建一个我无法发布的 Mutex
。
而且,如果我将参数 initiallyOwned
设置为 false
,谁真正拥有 Mutex
?
谢谢。
when will I need to create a Mutex
that I am not able to release it.
这个问题实在太宽泛了。但一个不太广泛的问题是:
How could I release a Mutex
that wasn't initially owned when I create it?
答案很简单:只需在创建 Mutex
之后获取它。然后就可以释放了。
And, if I set the parameter initiallyOwned
to false, who does really own that Mutex?
这取决于 Mutex
是否已被其他线程或进程创建和获取。如果不是,则 没有人 拥有它,您的代码稍后将能够获取它。
当然,对于你所处理的场景,你甚至不一定想要获得Mutex
。通常的方法是尝试 创建 Mutex
和 this constructor。如果您的代码实际创建了 Mutex
,则将设置第三个参数。您实际上永远不需要获取它;您只是在使用 OS 将确保 Mutex
只创建一次的事实。
请注意,已经有很多关于使用 .NET 编写单实例程序的非常好的建议。我强烈建议您查看此处找到的信息:
What is the correct way to create a single-instance WPF application?
How to restrict a program to a single instance
没有人拥有 Mutex
,除非有人通过调用它的方法 WaitOne
. Passing initiallyOwned: true
is an attempt to acquire immediately a newly created Mutex
, but it's problematic. From the documentation:
You should not use this constructor to request initial ownership, unless you can be certain that the thread will create the named mutex.
还有an overload接受三个参数:
public Mutex (bool initiallyOwned, string name, out bool createdNew);
...但是创建没有初始所有权的 Mutex
更简单,然后在您准备好被阻止时获取它(以防它恰好被其他人获取)。
mutex = new Mutex(initiallyOwned: false, APP_NAME);
mutex.WaitOne(); // Potentially blocking
刚刚编写了一个必须一次处理一次的简单程序,因此通过使用具有特定名称的键控 Mutex
来实现。
代码(简化)如下所示。
static readonly string APP_NAME = "MutexSample";
static void Main(string[] args)
{
Mutex mutex;
try
{
mutex = Mutex.OpenExisting(APP_NAME);
// At this point, with no exception,
// the Mutex is acquired, so there is another
// process running
// Environment.Exit(1); or something
}
catch (WaitHandleCannotBeOpenedException)
{
// If we could not acquire any mutex with
// our app name, let's create one
mutex = new Mutex(true, APP_NAME);
}
Console.ReadKey(); // Just for keeping the application up
// At some point, I just want to release
// the mutex
mutex.ReleaseMutex();
}
我的第一次尝试是像 new Mutex(false, APP_NAME)
一样实例化 Mutex
,但是调用 mutex.ReleaseMutex()
时抛出异常
System.ApplicationException: 'Object synchronization method was called from an unsynchronized block of code.'
刚刚注意到构造函数的第一个参数(initiallyOwned
)标记了创建Mutex
的当前线程是否拥有它,不出所料,一个线程不能释放一个Mutex
不属于该线程。
因此将此参数更改为 true
解决了该问题,如上面的代码所示。
嗯,我的问题是,该参数的全部意义是什么?我的意思是,我什么时候需要创建一个我无法发布的 Mutex
。
而且,如果我将参数 initiallyOwned
设置为 false
,谁真正拥有 Mutex
?
谢谢。
when will I need to create a
Mutex
that I am not able to release it.
这个问题实在太宽泛了。但一个不太广泛的问题是:
How could I release a
Mutex
that wasn't initially owned when I create it?
答案很简单:只需在创建 Mutex
之后获取它。然后就可以释放了。
And, if I set the parameter
initiallyOwned
to false, who does really own that Mutex?
这取决于 Mutex
是否已被其他线程或进程创建和获取。如果不是,则 没有人 拥有它,您的代码稍后将能够获取它。
当然,对于你所处理的场景,你甚至不一定想要获得Mutex
。通常的方法是尝试 创建 Mutex
和 this constructor。如果您的代码实际创建了 Mutex
,则将设置第三个参数。您实际上永远不需要获取它;您只是在使用 OS 将确保 Mutex
只创建一次的事实。
请注意,已经有很多关于使用 .NET 编写单实例程序的非常好的建议。我强烈建议您查看此处找到的信息:
What is the correct way to create a single-instance WPF application?
How to restrict a program to a single instance
没有人拥有 Mutex
,除非有人通过调用它的方法 WaitOne
. Passing initiallyOwned: true
is an attempt to acquire immediately a newly created Mutex
, but it's problematic. From the documentation:
You should not use this constructor to request initial ownership, unless you can be certain that the thread will create the named mutex.
还有an overload接受三个参数:
public Mutex (bool initiallyOwned, string name, out bool createdNew);
...但是创建没有初始所有权的 Mutex
更简单,然后在您准备好被阻止时获取它(以防它恰好被其他人获取)。
mutex = new Mutex(initiallyOwned: false, APP_NAME);
mutex.WaitOne(); // Potentially blocking