使用c# mutex,可以做到跨進程同步,實現應用程序只能單開,不能多開,參考:
單開.NET Core控制台項目,示例代碼:
using System; using System.Threading; namespace NetCoreMutex { class Program { private static Mutex mutex = null; //設為Static成員,是為了在整個程序生命周期內持有Mutex static void Main() { bool firstInstance; mutex = new Mutex(true, @"Global\MutexSampleApp", out firstInstance); try { if (!firstInstance) { Console.WriteLine("已有實例運行,輸入回車退出……"); Console.ReadLine(); return; } else { Console.WriteLine("我們是第一個實例!"); for (int i = 60; i > 0; --i) { Console.WriteLine(i); Thread.Sleep(1000); } } } finally { //只有第一個實例獲得控制權,因此只有在這種情況下才需要ReleaseMutex,否則會引發異常。 if (firstInstance) { mutex.ReleaseMutex(); } mutex.Close(); mutex = null; } } } }
使用Mutex需要注意的兩個細節:
- 可能你已經注意到了,例子中在給Mutex命名的字符串里給出了一個“Global\”的前綴。這是因為在運行終端服務(或者遠程桌面)的服務器上,已命名的全局 mutex 有兩種可見性。如果名稱以前綴“Global\”開頭,則 mutex 在所有終端服務器會話中均為可見。如果名稱以前綴“Local\”開頭,則 mutex 僅在創建它的終端服務器會話中可見,在這種情況下,服務器上各個其他終端服務器會話中都可以擁有一個名稱相同的獨立 mutex。如果創建已命名 mutex 時不指定前綴,則它將采用前綴“Local\”。在終端服務器會話中,只是名稱前綴不同的兩個 mutex 是獨立的 mutex,這兩個 mutex 對於終端服務器會話中的所有進程均為可見。即:前綴名稱“Global\”和“Local\”僅用來說明 mutex 名稱相對於終端服務器會話(而並非相對於進程)的范圍。最后需要注意“Global\”和“Local\”是大小寫敏感的。
- 既然父類實現了IDisposalble接口,那么說明這個類一定需要你手工釋放那些非托管的資源。所以必須使用try/finally,亦或我討厭的using,調用Close()方法來釋放Mutex所占用的所有資源!