互斥锁不能正常工作

本文关键字:工作 常工作 不能 | 更新日期: 2023-09-27 18:10:00

所以这段代码在program.cs中,应该检查连接是否可用,是否有另一个实例已经在运行。如果有,则消息框通知用户,并询问他是否确定要打开应用程序。下一个问题是:我打开应用程序,然后再打开它,显示消息框,但什么也没发生。我重复这个过程,只有在4-5次之后它才有效。然后,如果我再次打开,它会打开2个实例。

static void Main()
    { 
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        SqlConnection con123 = new SqlConnection(con123.Metoda());
        Mutex mut = null;
        try
        {
            mut = Mutex.OpenExisting("Tray minimizer");
        }
        catch
        {
        }
        if (mut == null)
        {
            mut = new Mutex(true, "Tray minimizer");
            Application.Run(new Form1());
            //Tell GC not to destroy mutex until the application is running and
            //release the mutex when application exits.
            GC.KeepAlive(mut);
            mut.ReleaseMutex();
        }
        else
        {
            //The mutex existed so exit
            mut.Close();

                DialogResult result = MessageBox.Show("AApplication is already working!Do you want to reopen it?", "Caution!", MessageBoxButtons.OKCancel);
                if (result == DialogResult.OK)
                {

                    foreach (Process p in System.Diagnostics.Process.GetProcessesByName("Name of application"))
                    {
                        try
                        {
                            p.Kill();
                          //  p.WaitForExit(); // possibly with a timeout
                            Application.Run(new Form1());
                        }
                        catch (Win32Exception winException)
                        {
                            // process was terminating or can't be terminated - deal with it
                        }
                        catch (InvalidOperationException invalidException)
                        {
                            // process has already exited - might be able to let this one go
                        }
                    }
                }
                //if (result == DialogResult.Cancel)
                //{

                //}
            }
            try
            {
                con123.Open();
                con123.Close();
            }
            catch
            {
                MessageBox.Show("Cant connect to server!!!", "Error!");
                Application.Exit();
            }

互斥锁不能正常工作

我会这样做:

bool mutexCreated = true;
using (Mutex mutex = new Mutex(true, "eCS", out mutexCreated))
{
    if (mutexCreated)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        SqlConnection con123 = new SqlConnection(con123.Metoda());
        Application.Run(new Form1());
    }
    else
    {
        DialogResult result = 
            MessageBox.Show("AApplication is already working!Do you want to reopen it?", "Caution!",
                                                MessageBoxButtons.OKCancel);
        if (result == DialogResult.OK)
        {
            foreach (Process p in System.Diagnostics.Process.GetProcessesByName("Name of application"))
            {
                try
                {
                    p.Kill();
                    Application.Run(new Form1());
                }
                catch (Win32Exception winException)
                {
                    // process was terminating or can't be terminated - deal with it
                }
                catch (InvalidOperationException invalidException)
                {
                    // process has already exited - might be able to let this one go
                }
            }
        }
    }
    try
    {
        con123.Open();
        con123.Close();
    }
    catch
    {
        MessageBox.Show("Cant connect to server!!!", "Error!");
        Application.Exit();
    }
}

您的版本的问题是互斥锁可能在不适当的时间被收集。

  1. 一旦你结束在"互斥存在"的路径,你永远不会释放互斥。你只需要杀死其他进程并再次启动你的应用程序,但永远不会提供一种方法来释放互斥锁,当你的新应用程序结束时。

  2. 你在foreach (Process)循环中启动你的应用程序,这意味着如果有多个进程已经在运行(也许所有的消息框),你将为每个进程启动你的应用程序。

  3. 这也意味着你不会启动你的应用程序,如果你实际上没有找到另一个进程来杀死。

您的else情况应该看起来像这样的伪代码:

dialogResult = MessageBox(...);
if (dialogResult == OK)
{
    foreach (var p in ...)
    {
        // Todo: make sure you do not kill the current process!
        p.Kill();
    }
    // now run the application
    Application.Run(new Form1());
    // now release the mutex
    mut.Release();
}
else
{
    mut.Close();
}

伪代码仍然需要一些异常处理,以确保在发生异常时正确释放互斥锁。

这解决你的问题了吗?而不是使用OpenExisting,它没有文档保证在失败时返回null,我使用Mutex构造函数,它接受一个out bool来确定互斥锁是否被创建或是否已经存在。启动应用程序并使用它执行任何操作(根据我所看到的部分猜测)都被移到了与创建互斥锁或关闭现有实例相关的所有操作之下。

步骤如下:

  1. 初始化runApp变量为true
  2. 尝试创建Mutex
  3. 检查Mutex是否已创建(不存在)
    • 如果Mutex没有创建,说明它已经存在
      • 询问用户是否想退出,等待互斥锁可用(表示强制退出现有应用程序实例完成)
      • 如果他们不想退出,设置runAppfalse
  4. 检查runApp标志是否仍然为真

    • 如果为true,则运行应用程序。返回后(窗体退出),尝试connection

      注意,这可能有一个错误,我不知道你是否打算阻止,因为你在应用程序。

  5. 释放互斥

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    SqlConnection con123 = new SqlConnection(con123.Metoda());
    string ProgramName = "Tray minimizer.exe";
    bool mutCreated = false;
    Mutex mut = new Mutex(true, ProgramName, out mutCreated);
    bool runApp = true;
    if (!mutCreated)
    {
        DialogResult result = MessageBox.Show("Application is already working! Do you want to reopen it?", "Caution!", MessageBoxButtons.OKCancel);
        if (result == DialogResult.OK)
        {
            foreach (Process p in System.Diagnostics.Process.GetProcessesByName(ProgramName))
            {
                try
                {
                    p.Kill();
                }
                catch { }
            }
            mut.WaitOne(); // Wait for ownership of the mutex to be released when the OS cleans up after the process being killed
        }
        else
        {
            runApp = false;
        }
    }
    if (runApp)
    {
        Application.Run(new Form1());
        try
        {
            con123.Open();
            con123.Close();
        }
        catch
        {
            MessageBox.Show("Cant connect to server!!!", "Error!");
            Application.Exit();
        }
        mut.ReleaseMutex();
    }