none
求解惑: 判断程序只启动一个实例带来的问题 RRS feed

  • 问题

  • 用Mutex判断应用程序只启动一个实例

    [STAThread] static void Main() { bool theFirstInstance; Mutex mutexConview = new Mutex(false, "Local\\" + "MyUniqueForConview", out theFirstInstance); if (theFirstInstance) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); GetPartNumber(); languageSetting(); ModbusInitialization(); //运行主画面 Application.Run(new MainForm()); //加入这句程序退出后产生异常 //mutexConview.ReleaseMutex(); } else { MessageBox.Show(Properties.FunctionRes.strProgramIsRunning,Properties.SystemRes.strMessageBoxCaptionSystem); Application.Exit(); }

    GC.KeepAlive(mutexConview);// 不加这句判断就不成功 }

    两个奇怪的现象:

    1。如果我不加最后的GC.KeepAlive(mutexConview), 那么判断就失败,也就是说仍然可以启动多个实例,加上这句就OK. 我推测是mutexConview被GC回收掉了,但是A)为什么会被回收掉呢? B)GC.KeepAlive(mutexConview)应该是程序退出的时候才执行吧?即Application.Run(new MainForm())执行完毕才执行吧,  那么加到这里为什么会起作用呢?

    2)我在程序的第一个实例执行完,进行mutexConview.ReleaseMutex(); 会发现: 程序的画面都退出了大概10多秒,Windows会提示 "XXX 程序停止工作...."的异常。

    是在搞不懂,请解惑。

    2012年5月19日 5:45

答案

  • 这是我们系统判断启动实例的代码

            /// <summary>
            /// 应用程序的主入口点。
            /// </summary>
            [STAThread]
            private static void Main()
            {
                GlobalMutex();
    
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
    
                //******启动代码**********
            }
    
            private static Mutex mutex = null;
            private static void GlobalMutex()
            {
                // 是否第一次创建mutex
                bool newMutexCreated = false;
                string mutexName = "Global\\" + "WareHouseMis";//系统名称,Global为全局,表示即使通过通过虚拟桌面连接过来,也只是允许运行一次
                try
                {
                    mutex = new Mutex(false, mutexName, out newMutexCreated);
                }
                catch (Exception ex)
                {
                    Console.Write(ex.Message);
                    System.Threading.Thread.Sleep(1000);
                    Environment.Exit(1);
                }
    
                // 第一次创建mutex
                if (newMutexCreated)
                {
                    Console.WriteLine("程序已启动");
                    //todo:此处为要执行的任务
                }
                else
                {
                    MessageUtil.ShowTips("另一个窗口已在运行,不能重复运行。");
                    System.Threading.Thread.Sleep(1000);
                    Environment.Exit(1);//退出程序
                }
    
    
            } 
    
    实际上是不需要写//mutexConview.ReleaseMutex();

    当new的时候系统会自动判断的

    mutex = new Mutex(false, mutexName, out newMutexCreated);

    最后那个问题估计你是没有是 Global 而使用了Local "Global\\" + "WareHouseMis";//系统名称,Global为全局


    给我写信: QQ我:点击这里给我发消息

    • 已标记为答案 菜鸟学VB 2012年5月19日 10:44
    2012年5月19日 7:35

全部回复

  • 这是我们系统判断启动实例的代码

            /// <summary>
            /// 应用程序的主入口点。
            /// </summary>
            [STAThread]
            private static void Main()
            {
                GlobalMutex();
    
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
    
                //******启动代码**********
            }
    
            private static Mutex mutex = null;
            private static void GlobalMutex()
            {
                // 是否第一次创建mutex
                bool newMutexCreated = false;
                string mutexName = "Global\\" + "WareHouseMis";//系统名称,Global为全局,表示即使通过通过虚拟桌面连接过来,也只是允许运行一次
                try
                {
                    mutex = new Mutex(false, mutexName, out newMutexCreated);
                }
                catch (Exception ex)
                {
                    Console.Write(ex.Message);
                    System.Threading.Thread.Sleep(1000);
                    Environment.Exit(1);
                }
    
                // 第一次创建mutex
                if (newMutexCreated)
                {
                    Console.WriteLine("程序已启动");
                    //todo:此处为要执行的任务
                }
                else
                {
                    MessageUtil.ShowTips("另一个窗口已在运行,不能重复运行。");
                    System.Threading.Thread.Sleep(1000);
                    Environment.Exit(1);//退出程序
                }
    
    
            } 
    
    实际上是不需要写//mutexConview.ReleaseMutex();

    当new的时候系统会自动判断的

    mutex = new Mutex(false, mutexName, out newMutexCreated);

    最后那个问题估计你是没有是 Global 而使用了Local "Global\\" + "WareHouseMis";//系统名称,Global为全局


    给我写信: QQ我:点击这里给我发消息

    • 已标记为答案 菜鸟学VB 2012年5月19日 10:44
    2012年5月19日 7:35
  • 谢谢,我最初把Mutex变量写在Main()里面了,所以不行,把它放到 Class Program 范围内就可以了。感谢您的指点。

    2012年5月19日 10:44
  • 不客气,能解决得到你的问题我也很开心的

    给我写信: QQ我:点击这里给我发消息

    2012年5月19日 11:54