2016-09-05 3 views
0

Dies ist mein Code:Mutex tötet Anwendung

protected override async void OnStartup(StartupEventArgs e) 
    { 
     // Used to check if we can create a new mutex 
     bool newMutexCreated = false; 

     try 
     { 
      // Create a new mutex object with a unique name 
      mutex = new Mutex(false, MutexName, out newMutexCreated); 
     } 
     catch (Exception ex) 
      when (ex is UnauthorizedAccessException || 
       ex is IOException || 
       ex is WaitHandleCannotBeOpenedException || 
       ex is ArgumentException) 
     { 
      Logger.Error("Error while launching application. Failed to check for other instances.", ex); 
      Shutdown((int)ExitCode.ApplicationAlreadyRunning); 
     } 

     // When the mutex is created for the first time 
     // we run the program since it is the first instance. 
     if (newMutexCreated) 
     { 
      await ContinueStartup(e); 
      return; 
     } 
     else 
     { 
      // Otherwise we get the first instance with that process name, 
      Process[] currentProcesses = Process.GetProcessesByName(AssemblyName); 
      IntPtr mainWindowHandle = currentProcesses[0].MainWindowHandle; 
      if (mainWindowHandle != IntPtr.Zero) 
      { 
       // maximize it, if it was minimized, and set it to foreground. 
       Logger.Info("Another instance of the application is already running."); 
       ShowWindow(mainWindowHandle, WindowShowNormal); 
       SetForegroundWindow(mainWindowHandle); 
      } 

      // Then shutdown this instance. 
      Logger.Info("Shutting down."); 
      Shutdown((int)ConsoleModeExitCode.ApplicationAlreadyRunning); 
     } 
    } 

    protected override void OnExit(ExitEventArgs e) 
    { 
     Logger.Info("Exiting application."); 

     // Close mutex. 
     mutex.Dispose(); 

     base.OnExit(e); 
    } 

Was hier passiert, ist, dass meine Anwendung einmal gestartet werden soll. Während es ausgeführt wird, sollte jeder Versuch, eine neue Instanz zu starten, die erste Instanz in den Vordergrund bringen.

Aber was wirklich passiert ist: Nach 2-10 Startversuchen wird die GUI der ersten Instanz gelöscht, der Prozess läuft noch und blockiert den Mutex und kann nur im TaskManager gelöscht werden. Wenn ich versuche, dieses Verhalten zu debuggen und die Anwendung in VisualStudio auszuführen, passiert es einfach nie. Der Versuch, die Anwendung 50 Mal zu öffnen, tötet sie nie, so dass ich den Ereignissen, die scheinbar auftreten, nicht folgen kann.

Ist es normales Verhalten des GarbageCollector? Es tötet die erste Instanz für den Fall, dass es hängt? Oder fehlt mir etwas?

+0

was meinst du "die GUI der ersten Instanz ist getötet"? Was genau passiert? – slawekwin

+3

Warum denken Sie, dass das etwas mit dem Mutex zu tun hat? Was bedeutet "getötet"? Hast du eine Ausnahme? Läuft der Prozess weiter? Auch 'Process.MainWindowHandle' ist nicht sehr nützlich - Sind Sie sicher, dass Sie ein gültiges Handle bekommen, und es auf die richtige Weise benutzen (Sie benutzen P/Invokes, so ist es durchaus möglich, dass Sie Dinge in einem hässliche Art und Weise)? Haben Sie die Rückgabewerte überprüft? Haben Sie die Dokumentation für 'ShowWindow' und' SetForegroundWindow' gründlich gelesen? – Luaan

+0

Ich meine, die Anwendung ist geöffnet, ich habe eine Instanz auf der TaskBar und kann darauf klicken und damit arbeiten. Und dann versuche ich eine Instanz als einen Prozess von einer anderen Anwendung zu öffnen, dieser Code wird in der zweiten Instanz ausgeführt und dann verschwindet die erste Instanz von TaskBar und bleibt nur als Prozess im TaskManager und blockiert neue Mutexe. – ecth

Antwort

0

Okay, als @Luaan erwähnte das Problem war nicht der Mutex. Ich reparierte meinen Code mit dieser Lösung:

https://stackoverflow.com/a/9059657/3319147

ShowWindowAsync und ein etwas anderer Umgang mit dem IntPtr-Wert des Griffs scheinen diese Weise mehr stabil zu machen. Konnte es seither nicht abstürzen. Für mich ist das genug Stabilität :)