我编写了一个示例控制台应用程序,该应用程序创建了一个互斥体,如下面的代码示例所示。我通过按Ctrl + F5(在没有调试器的情况下运行该应用程序)直接从Visual Studio(VS2013)启动此应用程序。对于控制台应用程序的第一个实例,我获取了互斥锁,并在控制台中显示以下行:
已建立新执行个体...
但是,当我Ctrl + F5再次使用创建控制台应用程序的第二个实例时,我在控制台中收到以下消息:
实例已获取...
即使我使用以下代码行在500ms之后明确释放了互斥锁:
mut.ReleaseMutex();
在获取互斥锁的同一线程中,我仍然看到控制台应用程序的第二个实例等待互斥锁被释放。
有人可以向我解释为什么会这样,如果我做错了什么,可以纠正我吗?据我了解,ReleaseMutex
应该从通过mut.WaitOne(0)
调用获取该互斥锁的同一线程中释放该互斥锁,以便应为所有等待获取互斥锁的线程提供所有权。但是,在这种情况下,我看不到它起作用。
如果我关闭获取互斥锁的第一个实例(仍然是我的第二个实例),并尝试使用启动第三个实例Ctrl+F5,我会看到有一个AbandonedMutexException
:
未处理的异常:System.Threading.AbandonedMutexException:由于放弃了互斥,等待已完成。
PS:有趣的是,如果我将false
互斥量构造函数作为
static Mutex mut = new Mutex(false, "Global\\test");
这有什么意义initiallyOwned
参数的
public Mutex(bool initiallyOwned, string name);
互斥体类的构造函数版本?
class Program
{
static Mutex mut = new Mutex(true, "Global\\test");
static void Main(string[] args)
{
if (IsInstance())
{
Console.WriteLine("New Instance created...");
}
else
{
Console.WriteLine("Instance already acquired...");
}
Console.ReadLine();
}
static bool IsInstance()
{
if (!mut.WaitOne(0))
{
Console.WriteLine("Thread id {0} Waiting at Mutex...",AppDomain.GetCurrentThreadId());
return false;
}
else
{
Console.WriteLine("Thread id {0} got Mutex...", AppDomain.GetCurrentThreadId());
Thread.Sleep(500);
mut.ReleaseMutex();
return true;
}
}
}
因此,要了解一个问题,您需要了解两件事:
initiallyOwned
参数如何工作如果Mutex
使用initiallyOwned
= true创建-仅当尚未创建此类互斥量时,它将尝试立即获取所有权BUT。因此,应用程序的第一个实例立即获得了互斥锁的所有权。它与执行操作大致相同:
var mut = new Mutex(false, "Global\\test");
mut.WaitOne();
如果此互斥锁已经存在,它将不会尝试获取所有权。要查看是否创建了互斥锁(因此,它已经拥有它了),可以使用以下重载:
bool createdNew;
mut = new Mutex(true, "Global\\test", out createdNew);
现在,Mutex
允许从同一线程多次调用WaitOne
和ReleaseMutex
。如果您WaitOne
多次呼叫-您需要呼叫ReleaseMutex
相同的次数才能释放它。但是,对于第一个实例,您调用了WaitOne
两次:第一次是由于initiallyOwned
参数(并且因为互斥体尚不存在并且已创建),第二次是您明确地调用它。但是您只调用ReleaseMutex
一次,因此互斥锁不会释放,而是由第一实例拥有。当您关闭此实例时-互斥体仍未释放,因此被放弃。
这是说明这些要点的代码示例:
static Mutex mut;
static void Main(string[] args)
{
bool createdNew;
mut = new Mutex(true, "Global\\test", out createdNew);
if (createdNew) {
Console.WriteLine("New instance created with initially owned = true");
}
else if (IsInstance())
{
Console.WriteLine("New Instance created...");
}
else
{
Console.WriteLine("Instance already acquired...");
}
if (createdNew)
{
Thread.Sleep(500);
mut.ReleaseMutex();
}
Console.ReadLine();
}
static bool IsInstance()
{
if (!mut.WaitOne(0))
{
Console.WriteLine("Thread id {0} Waiting at Mutex...", AppDomain.GetCurrentThreadId());
return false;
}
else
{
Console.WriteLine("Thread id {0} got Mutex...", AppDomain.GetCurrentThreadId());
Thread.Sleep(500);
mut.ReleaseMutex();
return true;
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句