Mutex 不会同时停止来自 运行 的两个程序实例

Mutex does not stop two instances of program from running at once

我正在尝试使用 Mutex 一次只允许我的程序的一个实例 运行。我重用了我正在编写的另一个程序中的 Mutex 代码,结果发现它并没有阻止我的程序的两个实例同时变为 运行。但是,我的 Mutex 代码在我的其他程序中有效。下面是Program.cs的全部代码(打开文件的代码无关)。您能否解释一下我应该如何正确使用 Mutex 来防止我的程序的多个实例一次 运行?谢谢!

注意:我的原始代码基于这个 SO 答案:

using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace NTCSAttendanceKiosk
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // Make a mutex and detect if another instance of the program is running
            Mutex mutex = new Mutex(true, "AtteNTCSKioskMutex", out bool mutexResult);

            if (!mutexResult)
            {
                // Exit if it's already running
                return;
            }

            // Prevent the mutex from being released by the GC
            GC.KeepAlive(mutex);

            // Read the connection string from the file
            try
            {
                SqlConnectionInfo.ConnectionString = File.ReadAllText(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "\kiosk_config\connection_string.txt");
            }
            catch (FileNotFoundException)
            {
                MessageBox.Show("The file connection_string.txt does not exist. Please place the connection string in that file and place it in <your user folder>\kiosk_config\. The kiosk program will now exit.", "Connection String File Not Found", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            catch (IOException)
            {
                MessageBox.Show("File I/O error when loading connection_string.txt. The kiosk program will now exit.", "File I/O Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // Read the kiosk location name from the file
            try
            {
                SqlConnectionInfo.KioskLocation = File.ReadAllText(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "\kiosk_config\location.txt");
            }
            catch (FileNotFoundException)
            {
                MessageBox.Show("The file location.txt does not exist. Please place the kiosk location name in that file and place it in <your user folder>\kiosk_config\. The kiosk program will now exit.", "Connection String File Not Found", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            catch (IOException)
            {
                MessageBox.Show("File I/O error when loading location.txt. The kiosk program will now exit.", "File I/O Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            Application.Run(new KioskForm());
        }
    }
}

您可以通过 运行 多个实例同时测试以下代码。

static void Main(string[] args)
{
    using (var mutex = new Mutex(true, "UniqueSystemWideMutexName"))
    {
        //Timeout is set to zero so we don't block
        if (!mutex.WaitOne(0))
        {
            Console.WriteLine("Program already running");
            Console.ReadKey();
            return;
        }
        Console.WriteLine("This is the only program running");
        Console.ReadKey();
    }
}

如果您出于某种原因无法使用 Dispose,而 using 块为我们所做的,请务必调用 ReleaseMutex.

您也可以使用 OpenExisting 检查互斥体是否已经创建,但对于这个简单的用例来说没有必要。