通常需要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那本书吧。。。

posted on 2009-03-17 13:42  熵星尘  阅读(1496)  评论(1编辑  收藏  举报