2011-03-21 46 views
14

Estoy tratando de usar el método mutex para permitir que solo se ejecute una instancia de mi aplicación. Es decir, solo deseo un máximo de una instancia para todos los usuarios en una máquina. He leído varios otros temas sobre este tema y la solución parece bastante sencilla, pero en las pruebas no puedo ejecutar mi segunda instancia. Aquí está mi código ...WPF mutex para instancia de aplicación única que no funciona

public partial class App : Application 
{ 
    protected override void OnStartup(StartupEventArgs e) 
    { 
     // check that there is only one instance of the control panel running... 
     bool createdNew = true; 
     using (Mutex instanceMutex = new Mutex(true, @"Global\ControlPanel", out createdNew)) 
     { 
      if (!createdNew) 
      { 
       Application.Current.Shutdown(); 
       return; 
      } 
     } 

     base.OnStartup(e); 
    } 
} 

Respuesta

29

También está disponiendo la exclusión mutua en el mismo método, por lo que el mutex sólo vive para la duración del método. Almacene el mutex en un campo estático y manténgalo con vida mientras dure su aplicación.

+0

+1. Ya me gané;) –

+2

Gracias @Willem van Rumpt (y @OJ). Eso funciona. Creí equivocadamente que el Mutex era realmente algo detrás de la escena, más a nivel del sistema, y ​​la instancia del objeto Mutex no era importante.He incluido mi nuevo código a continuación para referencia futura ... – flobadob

+0

@OJ: Es bueno estar en el lado "ganador" para un cambio :) –

4

Está destruyendo el Mutex inmediatamente después de haberlo creado y probado. Debe mantener activa la referencia Mutex durante toda la vida de su aplicación.

Haga de Mutex un miembro/campo de su clase de Aplicación. Libere el mutex cuando su aplicación se apaga.

25

Aquí está mi nuevo código que tiene la respuesta proporcionada por @Willem van Rumpt (y @OJ) ...

public partial class App : Application 
{ 
    private Mutex _instanceMutex = null; 

    protected override void OnStartup(StartupEventArgs e) 
    { 
     // check that there is only one instance of the control panel running... 
     bool createdNew; 
     _instanceMutex = new Mutex(true, @"Global\ControlPanel", out createdNew); 
     if (!createdNew) 
     { 
      _instanceMutex = null; 
      Application.Current.Shutdown(); 
      return; 
     } 

     base.OnStartup(e); 
    } 

    protected override void OnExit(ExitEventArgs e) 
    {   
     if(_instanceMutex != null) 
      _instanceMutex.ReleaseMutex(); 
     base.OnExit(e); 
    } 
} 
1

me puede sugerir un enfoque mucho más limpio que también introduce el concepto de utilidad de anular la Método principal en la aplicación WPF. Además, si utiliza su solución, eche un vistazo al administrador de tareas, verá que la nueva instancia realmente alcanza el estado de ejecución (puede ver un nuevo proceso creado en la lista de tareas) y luego se cierra de repente. El enfoque propuesto en la publicación que sigue evitará este inconveniente también. http://blog.clauskonrad.net/2011/04/wpf-how-to-make-your-application-single.html

0

lo hice desde este enlace sólo tiene que añadir la clase dada y una sola línea en le App.xaml.cs http://wpfsingleinstance.codeplex.com/

public partial class App : Application  
{ 
    protected override void OnStartup(StartupEventArgs e) 
    { 
     WpfSingleInstance.Make(); //added this is the function of that class 
     base.OnStartup(e); 
    } 
} 
1

me dijeron para poner en práctica este enfoque de exclusión mutua en un WPF ya desarrollados aplicación que teníamos. El trabajo en torno al problema con el uso de anulación de la OnStart() que encontré fue en

App.g.cs 

Este archivo se encuentra en

obj\x86\debug\ 

y contiene la función main(), por lo que simplemente pone este pedazo de código en su función principal.

bool isOnlyInstance = false; 
Mutex m = new Mutex(true, @"WpfSingleInstanceApplication", out isOnlyInstance); 
if (!isOnlyInstance) 
{ 
    MessageBox.Show("Another Instance of the application is already running.", 
        "Alert", 
        MessageBoxButton.OK, 
        MessageBoxImage.Exclamation); 
    return; 
} 
GC.KeepAlive(m); 

pero para esto es necesario para mantener el BUILD ACTION de su conjunto App.xaml a ApplicationDefinition

NOTA: Esto podría no ser la mejor manera, ya que soy un principiante. (Por favor dígame si hay algo que debería cambiar)

2

Como muestra de extensión:

public static class Extension 
{ 
    private static Mutex mutex; 

    public static bool IsOneTimeLaunch(this Application application, string uniqueName = null) 
    { 
     var applicationName = Path.GetFileName(Assembly.GetEntryAssembly().GetName().Name); 
     uniqueName = uniqueName ?? string.Format("{0}_{1}_{2}", 
      Environment.MachineName, 
      Environment.UserName, 
      applicationName); 

     application.Exit += (sender, e) => mutex.Dispose(); 
     bool isOneTimeLaunch; 
     mutex = new Mutex(true, uniqueName, out isOneTimeLaunch); 
     return isOneTimeLaunch; 
    } 
} 

Aplicación Clase:

protected override void OnStartup(StartupEventArgs e) 
    { 
     if (this.IsOneTimeLaunch()) 
     { 
      base.OnStartup(e); 
     } 
     else 
     { 
      this.Shutdown(); 
     } 
    } 
+0

+1 para uniqueName para cada usuario. – slavoo

Cuestiones relacionadas