相信大家都知道在.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. elasticsearch 常用查询 + 删除索引 + 集群状态诊断

    1.多条件查询 curl -X POST \ http://10.0.0.42:9200/addressbook_user/_search \ -H 'cache-control: no-cache' ...

  2. Linux文件权限基础回顾介绍

    文件的权限 文件权限的概述: 权限贯穿运维的一生

  3. paper:Exploiting Query Reformulations for Web Search Result Diversification

    一. 使用查询重构来用于网页搜索结果多样性 paper本文贡献: 1. 提出了一个概率框架,这个框架显式地建模了模糊查询的信息需求---利用子查询, 2. 分析了子查询的有效性---从由三个搜索引擎提 ...

  4. Find Duplicate File in System

    Given a list of directory info including directory path, and all the files with contents in this dir ...

  5. 【LOJ】#3042. 「ZJOI2019」麻将

    LOJ#3042. 「ZJOI2019」麻将 如何判定一个集合牌有没有胡的子集是不是胡的 就用一个\(dp[j][k][0/1]\)表示有j个连续两个的串,有k个连续1个串,有没有对子,再记一下这个集 ...

  6. Redis 是怎么实现 “附近的人” 的?

    针对"附近的人"这一位置服务领域的应用场景,常见的可使用PG.MySQL和MongoDB等多种DB的空间索引进行实现. 而Redis另辟蹊径,结合其有序队列zset以及geohas ...

  7. linux内核编程入门 hello world

    注意: Makefile 文件的命名注意M需要大写,否则会报错. 在Makefile文件中make命令前应为tab制表符. 下文转载至:https://blog.csdn.net/bingqing07 ...

  8. HTML 标签的 for 属性

    HTML 标签的 for 属性 for 属性规定 label 与哪个表单元素绑定. 隐式和显式的联系 label通常以下面两种方式中的一种来和表单控件相联系: 将表单控件作为标记标签的内容,这样的就是 ...

  9. __declspec(dllexport)的作用

    加了之后发现,用ollydbg导入dll,可以自动判断某个函数是导出函数

  10. C/S软件方案

    互联网时代客户端软件的一些方案 纯Native开发, C++/C#/duilib+C++(Windows), Objective-c(Mac) Qt(Windows/Mac) NW.js/Electr ...