zoukankan      html  css  js  c++  java
  • Mutex实现单实例,你真的搞懂了吗?来看看吧。

    通常需要winform只运行一个实例的话,我们用这样一个方法
    修改Program.cs
    using System;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.Threading;

    namespace StudentGUI
    {
        
    static class Program
        {
            
    /// <summary>
            
    /// 应用程序的主入口点。
            
    /// </summary>
            [STAThread]
            
    static void Main()
            {
                
    bool IsRunning;
                Mutex mutex 
    = new Mutex(true"StudentGUI"out IsRunning);

                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(
    false);
                
    if (IsRunning)
                {
                    Application.Run(
    new Form1());
                }
            }
        }
    }

    然而,同样的代码在我的一个工程里做debug编译和release编译的结果就是不同。
    debug无论如何都是能正确的在第二个实例不执行Application.Run(new Form1()); 也就是IsRunning是false
    release版本如果你回去做个空的winform写上这样的代码保证你可以实现单实例效果, 但是!!我的工程里面release的IsRunning总是true
    也就是没有效果了。。。

    我花了很多时间去精简我的工程,到最后,我的工程只有了几个空的panel和一个form1的背景,仍然在release没有效果。
    这时候,我任意删掉一个panel,甚至换一个form1的backgroundimage都会正常起来。

    我疑惑的是什么情况下会使的这个IsRunning在release编译下总为Ture。
    当然我给客户一个debug编译是没有任何问题的,但是问题总是困扰我。

    我在CSDN上讨论后,有了这样的答案。

    Debug版延长了mutex的生命(以便被调试),而Release版则任由mutex被垃圾回收。
    如果前一个实例中的mutex被回收了,后一个实例当然侦测不到已经释放的mutex了。

    解决方法,把mutex写为静态成员:

    static class Program
    {
        
    static Mutex mutex;                      //<----

        [STAThread]
        
    static void Main()
        {
            
    bool IsRunning;
            mutex 
    = new Mutex(true"StudentGUI"out IsRunning);

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(
    false);
            
    if (!IsRunning)
            {
                Application.Run(
    new Form1());
            }
        }
    }
    或在程序末尾再次使用它,避免被垃圾回收:
    static void Main()
        {
            
    bool IsRunning;
            Mutex mutex 
    = new Mutex(true"StudentGUI"out IsRunning);

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(
    false);
            
    if (!IsRunning)
            {
                Application.Run(
    new Form1());
            }

            (mutex 
    as IDisposable).Dispose();      //<---
        }
    当然,还可以这样阻止被回收:
    [STAThread] 
            
    static void Main() 
            { 
                
    bool IsRunning; 
                Mutex mutex 
    = new Mutex(true"StudentGUI"out IsRunning); 
              
                Application.EnableVisualStyles(); 
                Application.SetCompatibleTextRenderingDefault(
    false); 

                
    if (IsRunning) 
                { 
                    Application.Run(
    new Form1()); 
                    GC.SuppressFinalize(mutex); 
                } 
            } 

    这个问题其实挺难,我和一个朋友甚至去看Mutex的源代码;

    这个问题其实也挺容易,release和debug的区别并不多,所以问题应该很容易找到;

    因为涉及多线程,还考虑过多线程的问题,应该说是Framework学的不够好,再去啃啃CLR Via那本书吧。。。

  • 相关阅读:
    hdu4587 Two Nodes 求图中删除两个结点剩余的连通分量的数量
    洛谷3388 tarjan割点
    POJ1523 Tarjan求割点以及删除割点之后强连通分量的数量
    POJ1144 tarjan+网络中割点与割边的数量
    POJ1780 欧拉路+手写栈解决爆战问题
    Delphi 窗体函数GetForegroundWindow
    Delphi 窗体函数GetClassName
    Delphi 窗体函数GetDesktopWindow
    Delphi 窗体函数 GetTopWindow、GetNextWindow
    Delphi 调用惯例 register, pascal, cdecl, stdcall, safecall 介绍
  • 原文地址:https://www.cnblogs.com/keyrratuff/p/1414249.html
Copyright © 2011-2022 走看看