2011-06-26 13 views
17

Duplicar posible:
What is the correct way to create a single instance application?Asegurar una sola instancia de aplicación

Tengo una aplicación Windows Forms, que se lanza una pantalla de inicio a través del siguiente código:

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; 

El arriba está en el código subyacente de la forma principal y se llama desde el controlador de eventos de carga.

Sin embargo, ¿cómo puedo asegurarme de que solo se cargue una instancia de la aplicación a la vez? En el controlador de eventos de carga del formulario principal, podría verificar si la lista de procesos está en el sistema (a través de GetProcessesByName (...)), pero ¿hay algún método mejor?

Usando .NET 3.5.

+1

Debe llamar 'Application.Run (SplashForm)' 'en lugar de un DoEvents)' lazo (. – SLaks

Respuesta

50

GetProcessesByName es una forma lenta de comprobar si se está ejecutando otra instancia. El método más rápido y elegante está usando 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 
    } 

Por favor tener en cuenta que el código que se presenta no es el mejor enfoque. Como se informó en uno de los comentarios que llaman DoEvents() en un bucle no es la mejor idea.

+0

GC.KeepAlive (mutex); - no funciona para mí por algunas razones. Fui forzado a usar mutex estático privado; – monstr

+0

Puedo estar equivocado, pero no debería 'GC.KeepAlive (mutex);' line be before 'Application.Run (new Form1());'? El método 'Application.Run()' inicia el ciclo de mensajes del programa y no regresa hasta que se cierra 'Form1'. –

+0

@AlexB .: no, esto es a propósito. El objetivo es evitar que se libere mutex, lo que puede ocurrir cuando se abre un nuevo formulario y se cierra Form1. Antes de que se cierre el Form1, no hay riesgo de que se libere mutex – 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 
    } 
} 

Una nota sobre los algunos-única-id -> esto debe ser único en la máquina, por lo que usar algo como el nombre de la empresa Nombre/aplicación.

Editar:

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

Cuestiones relacionadas