互斥锁无法正常工作

时间:2013-04-19 17:49:02

标签: c# mutex

所以这段代码在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();
            }

3 个答案:

答案 0 :(得分:1)

我会做更多的事情:

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 :(得分:0)

  1. 一旦你进入“互斥锁存在”路径,就永远不会释放互斥锁。您只需删除任何其他进程并再次启动应用程序,但永远不会提供在新应用程序结束时释放互斥锁的方法。

  2. 您正在foreach (Process)循环中启动您的应用,这意味着如果有多个进程已在运行(可能所有进程都带有消息框),您将为每个进程启动应用。

  3. 这也意味着如果您实际上没有找到另一个要杀死的进程,则无法启动您的应用。

  4. 您的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();
    }
    

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

答案 2 :(得分:0)

这可以解决您的问题吗?我没有使用OpenExisting,它没有保证在失败时返回null的文档保证,而是使用Mutex构造函数来获取out bool来确定互斥锁是否已创建或者它是否已经存在。启动应用程序并对其执行任何操作(根据我所看到的内容进行部分猜测)将移至与创建互斥锁或关闭现有实例相关的所有内容之下。

现在步骤如下:

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

    • 如果确实如此,请运行该应用程序。返回后(表单退出),尝试连接

      请注意,这可能有错误,我不知道您是否打算在应用中阻止。

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