2011-06-26 4 views
17

thể trùng lặp:
What is the correct way to create a single instance application?Đảm bảo chỉ có một ứng dụng ví dụ

Tôi có một ứng dụng Winforms, mà ra mắt một màn hình thông qua các đoạn mã sau:

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; 

Các ở trên là trong codebehind của biểu mẫu chính và được gọi từ trình xử lý sự kiện tải.

Tuy nhiên, làm cách nào tôi có thể đảm bảo rằng chỉ một phiên bản của ứng dụng sẽ tải tại một thời điểm? Trong trình xử lý sự kiện tải của biểu mẫu chính, tôi có thể kiểm tra xem danh sách quy trình có trên hệ thống không (thông qua GetProcessesByName (...)), nhưng có phương pháp tốt hơn không?

Sử dụng .NET 3.5.

+1

Bạn nên gọi 'Application.Run (splashForm) 'thay vì một' DoEvents()' vòng lặp. – SLaks

Trả lời

50

GetProcessesByName là cách kiểm tra chậm nếu một phiên bản khác đang chạy. Phương pháp nhanh nhất và thanh lịch đang sử dụng mutex:

[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 
    } 

Cũng xin lưu ý rằng mã bạn trình bày không phải là cách tiếp cận tốt nhất. Như nó đã được khuyên trong một trong những ý kiến ​​gọi DoEvents() trong một vòng lặp không phải là ý tưởng tốt nhất.

+0

GC.KeepAlive (mutex); - không làm việc cho tôi bởi một số lý do. Tôi đã được forsed sử dụng mutex tĩnh riêng; – monstr

+0

Tôi có thể sai, nhưng không nên 'GC.KeepAlive (mutex);' dòng trước 'Application.Run (new Form1());'? Phương thức 'Application.Run()' bắt đầu vòng lặp tin nhắn của chương trình và không trở lại cho đến khi 'Form1' được đóng lại. –

+0

@AlexB .: không, đây là mục đích. Mục đích là để ngăn chặn mutex được phát hành, có thể xảy ra khi một hình thức mới được mở ra và Form1 được đóng lại. Trước khi Form1 được đóng lại, không có nguy cơ mutex được phát hành – 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 
    } 
} 

Một lưu ý về số duy nhất -> điều này phải là duy nhất trên máy, vì vậy hãy sử dụng tên công ty/tên ứng dụng của bạn.

Edit:

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