最近在做一個作業排程的ConsoleApp,作業排程部分本文暫不討論(以後會寫),本文只討論如何保證單一實例運作。
ConsoleApp運行要求
1、系統啟動時啟動該應用程式;
2、每會話狀態下單一實例運行;
開啟一個遠端桌面連結時,ConsoleApp只允許被啟動一個實例。
3、系統範圍內只能有一個實例運作;
開啟多個遠端桌面連結時,ConsoleApp只允許被啟動一個實例。
Mutex
Mutex(互斥體):一個同步基元,也可用於進程間同步。
可見MSND:http: //msdn.microsoft.com/zh-cn/library/system.threading.mutex.aspx
在官方文件的介紹中,有這樣一段話
在運行終端服務的伺服器上,已命名的系統mutex 可以具有兩級可見性。如果名稱以前綴「Global」開頭,則mutex 在所有終端伺服器會話中均為可見。如果名稱以前綴「Local」開頭,則mutex 僅在建立它的終端伺服器工作階段中可見。在這種情況下,伺服器上各個其他終端伺服器會話中都可以擁有一個名稱相同的獨立mutex。如果建立已命名mutex 時不指定前綴,則它將採用前綴「Local」。在終端伺服器會話中,只是名稱前綴不同的兩個mutex 是獨立的mutex,這兩個mutex 對於終端伺服器會話中的所有進程均為可見。即:前綴名稱「Global」和「Local」說明mutex 名稱相對於終端伺服器會話(而非相對於進程)的範圍。
很可惜沒有找到C#範例,這段話可以理解為:
mutexName= "Local\" +"AppName";
只對創建它的會話有效,也就是說新開啟一個遠端連結時會再次啟動ConsoleApp實例。
mutexName= "Global\" +"AppName";
對所有會話有效,開啟多個遠端連結時,只有第一個遠端連結會成功啟動ConsoleApp實例。
每會話狀態下單一實例運行
private static void LocalMutex()
{
// 是否第一次建立mutex
bool newMutexCreated = false;
string mutexName = "Local\" + "tenghoo";
Mutex mutex = null;
try
{
mutex = new Mutex(false, mutexName, out newMutexCreated);
}
catch (Exception ex)
{
Console.Write(ex.Message);
System.Threading.Thread.Sleep(3000);
Environment.Exit(1);
}
// 第一次建立mutex
if (newMutexCreated)
{
Console.WriteLine("程式已啟動");
//todo:此處為要執行的任務
}
else
{
Console.Write("另一個視窗已在運行,3秒以後自動關閉。");
System.Threading.Thread.Sleep(1000);
Console.Write("1");
System.Threading.Thread.Sleep(1000);
Console.Write("2");
System.Threading.Thread.Sleep(1000);
Console.Write("3");
Environment.Exit(1);//退出程序
}
}
系統範圍內單一實例運行
private static void GlobalMutex()
{
// 是否第一次建立mutex
bool newMutexCreated = false;
string mutexName = "Global\" + "tenghoo";
Mutex mutex = null;
try
{
mutex = new Mutex(false, mutexName, out newMutexCreated);
}
catch (Exception ex)
{
Console.Write(ex.Message);
System.Threading.Thread.Sleep(3000);
Environment.Exit(1);
}
// 第一次建立mutex
if (newMutexCreated)
{
Console.WriteLine("程式已啟動");
//todo:此處為要執行的任務
}
else
{
Console.Write("另一個視窗已在運行,3秒以後自動關閉。");
System.Threading.Thread.Sleep(1000);
Console.Write("1");
System.Threading.Thread.Sleep(1000);
Console.Write("2");
System.Threading.Thread.Sleep(1000);
Console.Write("3");
Environment.Exit(1);//退出程序
}