相信大家都知道在.NET程式中若要實現單一程式執行個體,一般來說有幾種方法,像是去判斷是否已經有開啟的Process是相同的程式、用Mutex與Semaphore之類的技術來判斷是否程式正在開啟。但是很多網路上的文章都忽略了在用Mutex實現單一程式執行個體時,其實會有些必須要注意的地方,導致於在實際運用上沒有發揮到該有的效果。

以一個簡單的例子來看,一般我們在網路上常看到的使用方式大概就像下面的程式碼片段類似,建構Mutex時就會回傳該Mutex是否已經存在,利用該回傳值來決定程式應該繼續開啟還是關閉。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Threading; namespace WindowsFormsApplication10
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Boolean bCreatedNew; //Create a new mutex using specific mutex name
Mutex m = new Mutex(false, "myUniqueName", out bCreatedNew); if (bCreatedNew)
Application.Run(new Form1());
}
}
}

這樣的程式到底有什麼樣的問題呢?有興趣的可以試著建置Release的程式看看,其實這樣的程式在某些情況下會在Release模式下失效,Debug的運作卻是正常的,若試不出來的可以再加上個GC.Collect試試,會更容易重現。

...
Boolean bCreatedNew; //Create a new mutex using specific mutex name
Mutex m = new Mutex(false, "myUniqueName", out bCreatedNew); GC.Collect(); if (bCreatedNew)
Application.Run(new Form1());
...

之所以會有這樣的問題,是因為Mutex在Release模式下被GC給回收了,而Debug模式下因為便於開發人員除錯,據說有將GC的周期給拉長,所以不容易重現。那這樣的問題要怎麼樣解決呢?這邊筆者有整理了幾種方法。

一個方法就是把Mutex給拉出來成為類別成員。

...
static Mutex m; /// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Boolean bCreatedNew; //Create a new mutex using specific mutex name
m = new Mutex(false, "myUniqueName", out bCreatedNew);
GC.Collect(); if (bCreatedNew)
Application.Run(new Form1());
}
...

另一個方法就是讓Mutex不要被GC回收掉,像是在程式最後明確呼叫Dispose,讓GC知道該Mutex仍在使用。

...
Boolean bCreatedNew; //Create a new mutex using specific mutex name
Mutex m = new Mutex(false, "myUniqueName", out bCreatedNew); GC.Collect(); if (bCreatedNew)
Application.Run(new Form1()); m.Dispose();
...

也可以用using或是try...finally之類的語法將Mutex給hold住。

...
Boolean bCreatedNew; //Create a new mutex using specific mutex name
using (Mutex m = new Mutex(false, "myUniqueName", out bCreatedNew))
{
GC.Collect(); if (bCreatedNew)
Application.Run(new Form1());
}
...

或是把Mutex的用法寫的比較正規一點,加上WaitOne與ReleaseMutex去明確控制Mutex的作用範圍。

...
Boolean bCreatedNew; //Create a new mutex using specific mutex name
Mutex m = new Mutex(false, "myUniqueName", out bCreatedNew); m.WaitOne();
GC.Collect(); if (bCreatedNew)
Application.Run(new Form1()); m.ReleaseMutex();
...

使用Mutex實現單一程式執行個體的注意事項(转)的更多相关文章

  1. System.Web.Compilation.BuildManager.CopyPrecompiledFile 並未將物件參考設定為物件的執行個體

    使用MSBUild 的 aspnet_compiler.exe 发布网站, 过程中出现错误 [NullReferenceException]: 並未將物件參考設定為物件的執行個體  System.W ...

  2. linux下c++實現簡單的生產者消費者隊列模式

    引言 生產者消費者是一個經典的模式 利用生產者,消費者和緩衝區降低了生產者和消費者之間的的耦合度 便於對生產者和消費者的修改 下面記錄的是一個經典的單一生產者多消費者的模式 設計思路 以隊列做為緩衝區 ...

  3. (STM32F4) IAP程式碼實現

    IAP學習, 主要想了解實際上程式碼放在不同的Flash位置如何轉跳且執行. 我的應用程序只做了Pin12, Pin13 LED閃爍來分辨我的 App1 跟 App2的程式碼 App1 程式碼 int ...

  4. ASP.NET MVC 4.0 学习2-留言板實現

    新增專案實現留言板功能,瞭解MVC的運行機制 1,新增專案   2,添加數據庫文件message.mdf   Ctrl+W,L 打開資料庫連接,添加存放留言的Atricle表 添加字段,後點擊&quo ...

  5. [Xamarin.Android] 結合Windows Azure與Google cloud message 來實現Push Notification (转帖)

    這一篇要討論如何使用Xamarin.Android 整合GCM以及Windows Azure來實作Android手機上的推播通知服務. 這篇文章比較著重概念的部分,在開始讀這篇之前,也可以先參考一下X ...

  6. [實現DDD] 第10章 聚合(1)設計原則

    聚合只是將一些實體(Entity)與值對象(Value Object)聚集起來的對象樹嗎?? 有些途徑可能使我們設計出不正確的聚合模型, 如:可能為了對象組合上的方便而將聚合設計的很大;也可能設計的聚 ...

  7. Jquery scrollTop animate 實現動態滾動到頁面頂部

    這個方法之前都是用的錨點實現的,但是效果僵硬,動感不足! 之後參考了一些網站,發現都是用的js,於是自己想到用jquery 來做一個插件也來實現以下這個小功能. $.fn.backTop = func ...

  8. 【转】Visual Studio單元測試小應用-測執行時間

    [转]Visual Studio單元測試小應用-測執行時間 Visual Studio的單元測試會記錄每一個測試的執行時間,如果有幾個Method要測效能,以前我會用Stopwatch,最近我都改用單 ...

  9. Neo4j中實現自定義中文全文索引

    資料庫檢索效率時,一般首要優化途徑是從索引入手,然後根據需求再考慮更復雜的負載均衡.讀寫分離和分散式水平/垂直分庫/表等手段:索引通過資訊冗餘來提高檢索效率,其以空間換時間並會降低資料寫入的效率,因此 ...

随机推荐

  1. Crunch黑客神器-创造个性字典

    先来看第一个命令: crunch 6 7 123456 -o pass.txt 是什么意思呢?我们打开终端,输入这个命令之后,crunch代表使用crunch这个工具,6代表生成的密码最小是6位数,7 ...

  2. 【图像处理】H.264开源解码器评测

    转自:http://wmnmtm.blog.163.com/blog/static/38245714201142883032575/ 要播放HDTV,就首先要正确地解开封装,然后进行视频音频解码.所以 ...

  3. 自然语言处理工具python调用hanlp的方法步骤

    Python调用hanlp的方法此前有分享过,本篇文章分享自“逍遥自在017”的博客,个别处有修改,阅读时请注意! 1.首先安装jpype 首先各种坑,jdk和python 版本位数必须一致,我用的是 ...

  4. Wordpress 所有 hook 钩子

    muplugins_loaded 在必须使用的插件加载之后. registered_taxonomy 对于类别,post_tag 等 Registered_post_type 用于帖子,页面等 plu ...

  5. MFC控件使用大全

    https://blog.csdn.net/daoming1112/article/details/54698113

  6. MySQL如何利用索引优化ORDER BY排序语

    MySQL索引通常是被用于提高WHERE条件的数据行匹配或者执行联结操作时匹配其它表的数据行的搜索速度. MySQL也能利用索引来快速地执行ORDER BY和GROUP BY语句的排序和分组操作. 通 ...

  7. MyBatis学习存档(1)——入门

    一.简介 MyBatis的前身是iBatis,本是Apache的一个开源的项目 MyBatis是一个数据持久层(ORM)框架,把实体类和SQL语句之间建立了映射关系,是一种半自动化的ORM实现 MyB ...

  8. Neo4j Cypher语法(二)

    目录 4 子句 4.1 CREATE 4.2 MATCH 4.3 Match 4.4 Create match return连用来返回一个关系基础 4.5 Optional_match 4.6 Wit ...

  9. centos7上搭建NFS的实践

    NFS 即network file system 可用于向k8s集群提供持久存储 最小化安装centos后  把网卡设置好了后 1.关闭防火墙 [root@NFS ~]# systemctl stop ...

  10. 发明专利定稿&递交申请啦,开心

    也不想写些什么,只是想简单的分享一下当前的心情! 第一版到最后一版中间因为各种事情耽误,一直弄到现在.5月中旬找的专利代理局中间连续修改很多次,从大改到小改,再到微调真的是学习到了! 下面就是搞定&l ...