刚刚编写了一个必须一次处理一次的简单程序,因此通过使用具有特定名称的键控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
?
谢谢。
没有人拥有Mutex
,除非它是由某人通过调用其方法WaitOne
获得的。传递initiallyOwned: true
是尝试立即获取新创建的Mutex
,但这是有问题的。来自文件:
您不应该使用此构造函数来请求初始所有权,除非您可以确定线程将创建命名的互斥体。
还有一个接受三个参数的重载:
public Mutex (bool initiallyOwned, string name, out bool createdNew);
但更简单的做法是,在没有初始所有权的情况下创建Mutex
,然后在准备被阻止时获取它(以防它碰巧被其他人获取(。
mutex = new Mutex(initiallyOwned: false, APP_NAME);
mutex.WaitOne(); // Potentially blocking
我什么时候需要创建一个无法发布的
Mutex
。
这个问题太宽泛了。但一个不那么宽泛的问题是:
创建
Mutex
时,如何发布它?
答案很简单:只需在创建后获取Mutex
。然后就可以发布它。
如果我将参数
initiallyOwned
设置为false,谁真正拥有Mutex?
这取决于Mutex
是否已经由其他线程或进程创建和获取。如果不是,那么没有人拥有它,您的代码稍后可以获得它。
当然,对于您正在处理的场景,您甚至不一定想要获得Mutex
。通常的方法是尝试使用此构造函数创建Mutex
。如果您的代码实际创建了Mutex
,则将设置第三个参数。你从来没有真正需要获得它;您只是在使用这样一个事实,即操作系统将确保Mutex
只创建过一次。
请注意,关于用.NET编写单实例程序,已经有很多非常好的建议了。我强烈建议您查看此处的信息:
创建单实例WPF应用程序的正确方法是什么
如何将程序限制为单个实例