通常需要winform只运行一个实例的话,我们用这样一个方法
修改Program.cs
修改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());
}
}
}
}
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 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(); //<---
}
当然,还可以这样阻止被回收: {
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);
}
}
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那本书吧。。。