使用Mutex實現單一程式執行個體的注意事項(转)
相信大家都知道在.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實現單一程式執行個體的注意事項(转)的更多相关文章
- System.Web.Compilation.BuildManager.CopyPrecompiledFile 並未將物件參考設定為物件的執行個體
使用MSBUild 的 aspnet_compiler.exe 发布网站, 过程中出现错误 [NullReferenceException]: 並未將物件參考設定為物件的執行個體 System.W ...
- linux下c++實現簡單的生產者消費者隊列模式
引言 生產者消費者是一個經典的模式 利用生產者,消費者和緩衝區降低了生產者和消費者之間的的耦合度 便於對生產者和消費者的修改 下面記錄的是一個經典的單一生產者多消費者的模式 設計思路 以隊列做為緩衝區 ...
- (STM32F4) IAP程式碼實現
IAP學習, 主要想了解實際上程式碼放在不同的Flash位置如何轉跳且執行. 我的應用程序只做了Pin12, Pin13 LED閃爍來分辨我的 App1 跟 App2的程式碼 App1 程式碼 int ...
- ASP.NET MVC 4.0 学习2-留言板實現
新增專案實現留言板功能,瞭解MVC的運行機制 1,新增專案 2,添加數據庫文件message.mdf Ctrl+W,L 打開資料庫連接,添加存放留言的Atricle表 添加字段,後點擊&quo ...
- [Xamarin.Android] 結合Windows Azure與Google cloud message 來實現Push Notification (转帖)
這一篇要討論如何使用Xamarin.Android 整合GCM以及Windows Azure來實作Android手機上的推播通知服務. 這篇文章比較著重概念的部分,在開始讀這篇之前,也可以先參考一下X ...
- [實現DDD] 第10章 聚合(1)設計原則
聚合只是將一些實體(Entity)與值對象(Value Object)聚集起來的對象樹嗎?? 有些途徑可能使我們設計出不正確的聚合模型, 如:可能為了對象組合上的方便而將聚合設計的很大;也可能設計的聚 ...
- Jquery scrollTop animate 實現動態滾動到頁面頂部
這個方法之前都是用的錨點實現的,但是效果僵硬,動感不足! 之後參考了一些網站,發現都是用的js,於是自己想到用jquery 來做一個插件也來實現以下這個小功能. $.fn.backTop = func ...
- 【转】Visual Studio單元測試小應用-測執行時間
[转]Visual Studio單元測試小應用-測執行時間 Visual Studio的單元測試會記錄每一個測試的執行時間,如果有幾個Method要測效能,以前我會用Stopwatch,最近我都改用單 ...
- Neo4j中實現自定義中文全文索引
資料庫檢索效率時,一般首要優化途徑是從索引入手,然後根據需求再考慮更復雜的負載均衡.讀寫分離和分散式水平/垂直分庫/表等手段:索引通過資訊冗餘來提高檢索效率,其以空間換時間並會降低資料寫入的效率,因此 ...
随机推荐
- linux中查找命令find、locate、whereis、which、type的区别
find find是最常见和最强大的查找命令,你可以用它找到任何你想找的文件.与查询数据库(/var/lib/locatedb)文件不同,find查找的是磁盘空间. locate locate命令其实 ...
- Spark2.0学习记录
Hadoop与Spark的关系: ------------------- Spark 与mapReduce的区别: mapReduce和spark的内存结构: ------------------- ...
- Stream系列(十)Count方法使用
计数器 视频讲解: https://www.bilibili.com/video/av77905733/ EmployeeTestCase.java package com.example.demo; ...
- Java-Redis 热部署问题
项目请求时报错: java.lang.ClassCastException: cn.xingaohbd.seckil.model.User cannot be cast to cn.xingaohbd ...
- Nuxt的动态路由及路由校验入门
其实动态路由就是带参数的路由.比如我们现在新闻模块下面有很多新闻详情页,这时候就需要动态路由的帮助了. 新闻详细页面我们在news文件夹下面新建了_id.vue的文件,以下划线为前缀的Vue文件就是动 ...
- kettle 创建作业发送邮件
1.创建作业 . 2. 发送邮件配置,测试邮件 发件地址可以使用的QQ.126.163等邮箱 smtp server的填写smtp.qq.com或者smtp.126.com等等都可以这里我用Q163邮 ...
- redis 慢查询、Pipeline
1.慢查询 简介 慢查询顾名思义是将redis执行命令较慢的命令记录下来,redis处理慢查询时是将慢查询记录到慢查询队列中 慢查询配置 slowlog-max-len 慢查询队列长度(记录多少条慢查 ...
- Djangon简介
目录 Djangon简介 MVC与MTV模型 MVC MTV python三大主流web框架 Django的下载与基本命令 基于Django实现的一个简单示例 Django静态文件配置 Django ...
- linux查询cpu过高原因--java
1. 查询java pid top -c 2. 查询java进程下,线程情况 top -Hp pid(threadIdList) 3. 将10进制线程id转为16进制 printf "%x ...
- 【原创】大数据基础之Drill(1)简介、安装及使用
https://drill.apache.org/ 一 简介 Drill is an Apache open-source SQL query engine for Big Data explorat ...