0

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

3 回答 3

2

我会做更多类似的事情:

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

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

于 2013-04-19T18:31:15.837 回答
0
  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();
}

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

于 2013-04-19T18:33:51.617 回答
0

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

现在的步骤如下:

  1. runApp将变量初始化为真
  2. 尝试创建Mutex
  3. 检查是否Mutex已创建(尚不存在)
    • 如果Mutex没有创建,它已经存在
      • 询问用户是否要退出,等待互斥量可用(表示强制退出现有应用实例完成)
      • 如果他们不想退出,请设置runAppfalse
  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();
    }
    
于 2013-04-19T18:34:35.010 回答