我理解Mutex can be used只允许我的应用的一个实例在一台计算机上启动。这意味着无论任意数量的用户使用了多少台桌面,最多只能运行一个程序实例。
现在,我不想只允许一个实例,而是希望最多允许两个,仅此而已。怎么做?我尝试过这样的代码:
public static bool MutexChecking()
{
bool createNew1;
// one set of GUID
new Mutex(false, "54A8F2C1-6C11-4ED4-8A62-AD7C1D9F7970", out createNew1);
if (createNew1)
return true;
bool createNew2;
//another set
new Mutex(false, "5E1C76D0-9897-412B-BD56-64A872F8FDE3", out createNew2);
return createNew2;
}
上面的代码有点......它适用于我测试的所有情况,除了这一个:
p1
)p2
)p1
。p3
)p3
期间,上述方法应返回true(因为createNew1
应为true
),但它返回false(因为createNew1
返回{{ 1}})。 为什么会这样?知道如何解决这个问题吗?
答案 0 :(得分:1)
你想要的是信号量,而不是互斥量。互斥锁处理互斥,信号量将共享资源的使用限制为最大数量。
答案 1 :(得分:0)
这是因为在p2中你再次打开第一个互斥锁。这个互斥锁保持打开状态,因为p2保持打开状态。当你打开第一个互斥锁并发现它已经打开时,你应该关闭它,所以p2只保持第二个互斥锁打开而p1只保持第一个互斥锁打开。
答案 2 :(得分:0)
简单。你错了out参数的点(createdNew)。来自the docs:
当此方法返回时,包含一个布尔值,如果是本地,则为true 创建了互斥锁(即,如果name为null或空字符串)或者是 创建了指定的命名系统互斥锁;如果指定则为false 命名系统互斥锁已经存在。传递此参数 初始化。
在您的情况下,p2
已经创建了第一个互斥锁,因此它不是“新建的”。
您要做的不是依赖于应用程序创建互斥锁,而是依赖拥有互斥锁。尝试传递true
作为第一个参数,并在应用程序退出时调用ReleaseMutex。
或者,切换到@ChrisLatta建议的命名信号量。
答案 3 :(得分:0)
Chris Shain所说的是正确的。你需要做的是拥有互斥锁,而不仅仅是创建互斥锁。此外,您必须在退出应用程序时手动释放互斥锁,否则其他应用程序实例可能会遇到 AbandonedMutexException 。
以下是您可能希望如何实现它的简单代码示例。请注意,此特定代码要求相同的线程调用StartInstance()和StopInstance()。
private static Mutex Mutex1 = new Mutex(false, "54A8F2C1-6C11-4ED4-8A62-AD7C1D9F7970");
private static Mutex Mutex2 = new Mutex(false, "5E1C76D0-9897-412B-BD56-64A872F8FDE3");
private static Mutex AcquiredMutex;
public static bool StartInstance()
{
if (AcquiredMutex != null)
return true;
if (Mutex1.WaitOne(1))
{
AcquiredMutex = Mutex1;
}
else if (Mutex2.WaitOne(1))
{
AcquiredMutex = Mutex2;
}
return (AcquiredMutex != null);
}
public static void StopInstance()
{
if (AcquiredMutex != null)
AcquiredMutex.ReleaseMutex();
}
编辑:实际上,如果您想使用 createNew 作为检测多个实例的方法,您可能会这样做,但我个人不建议这样做Mutex不是为此而设计的。
但是,即使您决定使用 createNew 方法,您仍需要在应用程序退出后自己明确地关闭互斥锁。
此方法可能比前一个方法具有的一个优点是,Close()方法不必由创建它的同一线程调用。
下面是一个使用 createNew 方法的简单代码示例。请注意,它不是线程安全的。您需要在StartInstance()和StopInstance()中使用lock()以使其成为线程安全的。
private static readonly string[] MutexNames = new string[]
{
"54A8F2C1-6C11-4ED4-8A62-AD7C1D9F7970",
"5E1C76D0-9897-412B-BD56-64A872F8FDE3"
};
private static Mutex CreatedMutex;
public static bool StartInstance()
{
if (CreatedMutex != null)
return true;
foreach (string name in MutexNames)
{
bool created;
Mutex mutex = new Mutex(false, name, out created);
if (created)
{
CreatedMutex = mutex;
return true;
}
else
{
mutex.Close();
}
}
return false;
}
public static void StopInstance()
{
if (CreatedMutex != null)
CreatedMutex.Close();
}