从Visual Studio启动时,C#ReleaseMutex()不会在控制台应用程序的多个实例中释放互斥量

阿尔比

我编写了一个示例控制台应用程序,该应用程序创建了一个互斥体,如下面的代码示例所示。我通过按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);

互斥体类的构造函数版本?

从VS运行2个实例的控制台输出

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;
        }
    }

}
EVK

因此,要了解一个问题,您需要了解两件事:

  1. initiallyOwned参数如何工作
  2. Mutex重入(递归调用)。

如果Mutex使用initiallyOwned= true创建-仅当尚未创建此类互斥量时,它将尝试立即获取所有权BUT。因此,应用程序的第一个实例立即获得了互斥锁的所有权。它与执行操作大致相同:

 var mut = new Mutex(false, "Global\\test");
 mut.WaitOne();

如果此互斥锁已经存在,它将不会尝试获取所有权。要查看是否创建了互斥锁(因此,它已经拥有它了),可以使用以下重载:

bool createdNew;
mut = new Mutex(true, "Global\\test", out createdNew);

现在,Mutex允许从同一线程多次调用WaitOneReleaseMutex如果您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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

启动时Visual Studio Community 2015控制台应用程序错误

在控制台应用程序上启动而不调试时 Visual Studio 延迟

在Visual Studio Code中,在外部窗口中启动控制台应用程序

从Visual Studio目录中删除C#控制台应用程序时挂起

C# 在控制台应用程序中构建 Visual Studio 项目

Visual Studio 2015“窃取”应用程序的控制台

Visual Studio(MAC)控制台应用程序

控制台应用程序完成退出(Visual Studio)

从MenuStrip启动控制台应用程序(Visual C#)

防止在Visual Studio C / C ++控制台应用程序上关闭控制台窗口

Visual Studio Windows 控制台应用程序在从 main() 返回 0 时抛出异常

在Visual Studio 2015社区中为现有C#控制台应用程序创建服务安装程序

在Visual Studio 2015中重新加载Designer时,为什么会弹出控制台应用程序?

控制台窗口不再出现在我的Visual Studio节点控制台应用程序中

Visual Studio 2015中没有控制台应用程序?

如何在Visual Studio控制台应用程序中终止脚本

控制台应用程序中的.NET System.MissingMethodException错误(Visual Studio 2015)

无法在Visual Studio社区版中更改控制台应用程序的图标

网络不适用于Visual Studio 2015中的控制台应用程序

无法在 Visual Studio 2019 中创建 .NET 5 控制台应用程序

Visual Studio C ++控制台应用程序生成并运行,但未创建EXE文件

如何修改 Visual Studio 的 C# .Net Core 控制台应用程序项目模板

C#控制台应用程序的Visual Studio代码

Visual Studio C# 控制台应用程序 (.NET Core) 模板不同

默认 Visual Studio C++ 控制台应用程序有 409 错误

在其他项目Visual Studio中使用控制台应用程序类中的c ++类

在 Visual Studio for Mac 8.6.2 中运行 C# 控制台应用程序时使用系统终端

控制台应用程序控制台窗口-Visual C ++

为什么在 Visual Studio 中用 C++ 编写 GUI 应用程序的代码与控制台应用程序不同?