惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
Stack Overflow Blog
Stack Overflow Blog
人人都是产品经理
人人都是产品经理
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
Vercel News
Vercel News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Y
Y Combinator Blog
The Cloudflare Blog
Last Week in AI
Last Week in AI
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
V
Visual Studio Blog
博客园 - 三生石上(FineUI控件)
小众软件
小众软件
Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
博客园 - 司徒正美
B
Blog RSS Feed
Microsoft Azure Blog
Microsoft Azure Blog
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
L
LangChain Blog

博客园 - 熵星尘

苦逼的程序员都是这么玩游戏的(微信:天天连萌) 关于ASP.NET动态加载控件的几点实用总结 记录代码运行耗时的写法 关于Linq to DataTable not in的写法 DevExpress AspxGridView数据绑定 发现一个Membership的bug 无法将类型为“Oracle.DataAccess.Types.OracleString”的对象强制转换为类型“System.String”。 asp.net页面中文件下载的2种方式 - 熵星尘 - 博客园 gridview 的添加删除等技巧 全部按名称取值 【部分转】innerText 跟 innerHTML区别 asp.net验证组件membership登录失败的问题 母板页中的引用的图片,JS,css等路径问题 - 熵星尘 - 博客园 如何获取GridView的EmptyDataTemplate中的控件 VS2008 如何在WinForm中显示flash - 熵星尘 - 博客园 【原创】从图像转换到byte[]数组的几种方法 除夕晚的一帖:如何为repeater内部控件设置javascript,如何取得它们的客户端ID。 回发或回调参数无效。 问题的解决和思考 - 熵星尘 - 博客园 【作品发布】正式发布Tuff的神奇小软盘1.2 【作品发布】QQ2008远程自助 1.5.1.1
Mutex实现单实例,你真的搞懂了吗?来看看吧。
熵星尘 · 2009-03-17 · via 博客园 - 熵星尘

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