2011-06-26 49 views
17

可能重複:
What is the correct way to create a single instance application?確保只有一個應用程序實例

我有一個WinForms應用程序,它通過下面的代碼啓動一個閃屏:

Hide(); 
     bool done = false; 
     // Below is a closure which will work with outer variables. 
     ThreadPool.QueueUserWorkItem(x => 
            { 
             using (var splashForm = new SplashScreen()) 
             { 
              splashForm.Show(); 
              while (!done) 
               Application.DoEvents(); 
              splashForm.Close(); 
             } 
            }); 

     Thread.Sleep(3000); 
     done = true; 

的上面是主窗體的代碼隱藏,並從加載事件處理程序調用。

但是,如何確保一次只加載一個應用程序實例?在主窗體的加載事件處理程序中,我可以檢查進程列表是否在系統上(通過GetProcessesByName(...)),但有沒有更好的方法?

使用.NET 3.5。

+1

你應該叫'Application.Run(splashForm)',而不是'的DoEvents()'循環。 – SLaks

回答

50

GetProcessesByName是檢查另一個實例是否正在運行的緩慢方式。最快最優雅的方法是使用互斥鎖:

[STAThread] 
    static void Main() 
    { 
     bool result; 
     var mutex = new System.Threading.Mutex(true, "UniqueAppId", out result); 

     if (!result) 
     { 
      MessageBox.Show("Another instance is already running."); 
      return; 
     } 

     Application.Run(new Form1()); 

     GC.KeepAlive(mutex);    // mutex shouldn't be released - important line 
    } 

請注意,您提供的代碼不是最好的方法。正如其中一條評論中所建議的,在循環中調用DoEvents()並不是最好的主意。對一些器唯一ID

+0

GC.KeepAlive(mutex); - 由於某些原因,不適合我。我被禁止使用私人靜態互斥體 ; – monstr

+0

我可能是錯的,但不應該'GC.KeepAlive(mutex);'在'Application.Run(new Form1());'之前? 'Application.Run()'方法啓動程序的消息循環,直到'Form1'關閉纔會返回。 –

+0

@亞歷克斯:不,這是故意的。目標是防止互斥體被釋放,當一個新窗體被打開並且Form1被關閉時可能會發生互斥體。在Form1關閉之前,如果block中沒有釋放互斥量 – michalczerwinski

16
static class Program 
{ 
    // Mutex can be made static so that GC doesn't recycle 
    // same effect with GC.KeepAlive(mutex) at the end of main 
    static Mutex mutex = new Mutex(false, "some-unique-id"); 

    [STAThread] 
    static void Main() 
    { 
     // if you like to wait a few seconds in case that the instance is just 
     // shutting down 
     if (!mutex.WaitOne(TimeSpan.FromSeconds(2), false)) 
     { 
      MessageBox.Show("Application already started!", "", MessageBoxButtons.OK); 
      return; 
     } 

     try 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      Application.Run(new Form1()); 
     } 
     finally { mutex.ReleaseMutex(); } // I find this more explicit 
    } 
} 

一個說明 - >這應該是機上唯一的,因此使用像您的公司名稱/應用程序名稱。

編輯:

http://sanity-free.org/143/csharp_dotnet_single_instance_application.html

相關問題