有時我們需要只允許運行應用程序的一個實例,當進程啟動時,如果發現應用程序的一個實例在運行,就自動停止運行。我們通常通過Mutex互斥體在Main函數中實現,通常的寫法是:
[STAThread]
static void Main()
{
bool createNew;
using (System.Threading.Mutex m = new System.Threading.Mutex(true, Application.ProductName, out createNew))
{
if (createNew)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
MessageBox.Show("Only one instance of this application is allowed!");
}
}
}
我們在尋找答案時,往往來去匆匆,根本不去理會Mutex的特性和注意事項。經過簡單的測試,OK,拿來就用。此時我們忽略了一個重要的前提條件:Mutex的命名規則。以上的寫法在單用戶下運行沒有問題;在多用戶下,每個用戶都能啟動一個實例,也就不能保證單實例運行了。
如果需要在終端機服務器上使用,並且只允許一個實例的話,請使用下面的寫法:
[STAThread]
static void Main()
{
bool createNew;
try
{
using (System.Threading.Mutex m = new System.Threading.Mutex(true, "Global\\" + Application.ProductName, out createNew))
{
if (createNew)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
MessageBox.Show("Only one instance of this application is allowed!");
}
}
}
catch
{
MessageBox.Show("Only one instance of this application is allowed!");
}
}
以下是MSDN的說明:
在運行終端服務的服務器上,已命名的系統 mutex 可以具有兩級可見性。如果名稱以前綴“Global\”開頭,則 mutex 在所有終端服務器會話中均為可見。如果名稱以前綴“Local\”開頭,則 mutex 僅在創建它的終端服務器會話中可見。在這種情況下,服務器上各個其他終端服務器會話中都可以擁有一個名稱相同的獨立 mutex。如果創建已命名 mutex 時不指定前綴,則它將采用前綴“Local\”。在終端服務器會話中,只是名稱前綴不同的兩個 mutex 是獨立的 mutex,這兩個 mutex 對於終端服務器會話中的所有進程均為可見。即:前綴名稱“Global\”和“Local\”說明 mutex 名稱相對於終端服務器會話(而並非相對於進程)的范圍。
摘自 JustRun1983