2011-06-26 11 views
17

Powiel możliwe:
What is the correct way to create a single instance application?Zapewnienie tylko jedna instancja aplikacji

Mam app WinForm, który uruchamia ekran powitalny za pomocą następującego kodu:

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; 

The powyżej znajduje się w kodzie głównym kodu formularza i wywoływana z procedury obsługi zdarzenia load.

Jak jednak upewnić się, że załadowane zostanie tylko jedno wystąpienie aplikacji? W procedurze obsługi zdarzeń obciążenia głównego formularza mogę sprawdzić, czy lista procesów znajduje się w systemie (przez GetProcessesByName (...)), ale czy istnieje lepsza metoda?

Korzystanie z platformy .NET 3.5.

+1

Należy zadzwonić 'Application.Run (splashForm)' zamiast od 'DoEvents()' loop. – SLaks

Odpowiedz

50

GetProcessesByName to powolny sposób sprawdzania, czy uruchomiona jest inna instancja. Najszybszy i elegancki sposób wykorzystuje 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 
    } 

Należy również pamiętać, że kod, który przedstawiony nie jest najlepszym rozwiązaniem. Jak informowano w jednym z komentarzy, wywołanie DoEvents() w pętli nie jest najlepszym pomysłem.

+0

GC.KeepAlive (mutex); - nie działa dla mnie z pewnych powodów. Zostałem zmuszony do użycia prywatnego statycznego muteksa o wartości ; – monstr

+0

Mogę się mylić, ale nie powinienem "GC.KeepAlive (mutex);" linia przed "Application.Run (nowy Form1());? Metoda "Application.Run()" uruchamia pętlę komunikatów programu i nie powraca, dopóki "Form1" nie zostanie zamknięty. –

+0

@AlexB .: nie, to jest celowe. Celem jest zapobieganie zwolnieniu muteksu, co może nastąpić, gdy nowy formularz zostanie otwarty, a Form1 zamknięty. Zanim Form1 zostanie zamknięty, nie ma ryzyka zwolnienia mutexa – 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 
    } 
} 

Jedna uwaga dotycząca unikalnego identyfikatora -> to powinno być unikalne na maszynie, więc użyj czegoś takiego jak nazwa firmy/nazwa aplikacji.

Edit:

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

Powiązane problemy