2010-05-28 14 views
6

Zuerst ein bisschen Hintergrund: Ich habe eine WPF-Anwendung, die eine GUI-Front-End zu einer älteren Win32-Anwendung ist. Die Legacy-App wird als DLL in einem separaten Thread ausgeführt. Die Befehle, die der Benutzer in der Benutzeroberfläche auswählt, werden in diesem "Legacy-Thread" aufgerufen.Application.Current.Shutdown() vs. Application.Current.Dispatcher.BeginInvokeShutdown()

Wenn der "Legacy-Thread" beendet ist, kann das GUI-Frontend nichts mehr tun, deshalb muss ich die WPF-Anwendung herunterfahren. Daher rufe ich am Ende der Methode des Threads Application.Current.Shutdown().

Da ich nicht auf dem Hauptthread bin, muss ich diesen Befehl aufrufen. Allerdings habe ich dann bemerkt, dass der Dispatcher auch BeginInvokeShutdown() hat, um den Dispatcher abzuschalten. Also meine Frage ist: Was ist der Unterschied

Application.Current.Shutdown(); 

zwischen Aufruf und ruft

Application.Current.Dispatcher.BeginInvokeShutdown(); 

Antwort

7

Ich habe einige Tests und jetzt denke ich, dass ich die Unterschiede kennen:

1) Wie in der MSDN-Seite angegeben, BeginInvokeShutdown neben den Dispatcher herunterzufahren, löscht auch/seiner Warteschlange abgebrochen. Shutdown behandelt zuerst alle Elemente in der Dispatcher-Warteschlange.

Sobald der Shutdown-Prozess beginnt, werden alle ausstehenden Arbeitselemente in der Warteschlange abgebrochen.

2) In einer Anwendung kann ich das Ereignis Application.Exit behandeln. Dieses Ereignis wird ausgelöst, wenn ich Shutdown anrufe, aber NICHT ausgelöst, wenn ich BeginInvokeShutdown aufruft! Gleiches gilt für Window.Closing und Window.Closed.

Als Ähnlichkeiten wird in beiden Fällen der Haupt-Thread beendet. Abhängig von anderen laufenden Threads wird dadurch auch der Prozess beendet: Non-Background-Threads werden bis zum Abschluss ausgeführt, bevor der Prozess beendet wird.

Unten ist mein Testcode. Kommentar der eine oder anderen Methodenaufruf in Application_Startup: Laufen separat WPF-Front-End zu einer Win32-COM (Delphi) Anwendung -

public partial class App 
{ 
    private void Application_Exit(object sender, ExitEventArgs e) 
    { 
     MessageBox.Show("Exiting"); 
    } 

    private void Application_Startup(object sender, StartupEventArgs e) 
    { 
     var testThread = new Thread(
      () => 
      { 
       Thread.Sleep(2000); 
       Application.Current.Dispatcher.BeginInvokeShutdown(System.Windows.Threading.DispatcherPriority.Send); 
       //Application.Current.Dispatcher.BeginInvoke(new Action(() => Application.Current.Shutdown())); 
      }); 
     testThread.Start(); 
    } 
} 

public partial class Window1 
{ 
    public Window1() 
    { 
     this.InitializeComponent(); 

     Dispatcher.BeginInvoke(new Action(() => 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("One"); 
     })); 

     Dispatcher.BeginInvoke(new Action(() => 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("Two"); 
     })); 

     Dispatcher.BeginInvoke(new Action(() => 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("Three"); 
     })); 

     Dispatcher.BeginInvoke(new Action(() => 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("Four"); 
     })); 
    } 

    private void Window_Closed(object sender, EventArgs e) 
    { 
     Console.WriteLine("Closed"); 
    } 

    private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
    { 
     Console.WriteLine("Closing"); 
    } 
} 
1

MSDN page for Shutdown()
MSDN page for BeginInvokeShutdown()

Es scheint, dass dies nur eine Kollision von Terminologie ist. BeginInvokeShutdown schließt die Dispatcher, Ihre Anwendung kann theoretisch weiterhin leben (obwohl ohne Dispatcher, würde es ziemlich begrenzt sein). Shutdown jedoch tatsächlich Ihre Anwendung beendet, was Sie wollen.

+0

Nun, das ist genau die Frage, die in der Dokumentation nicht beantwortet wird: Schaltet das Herunterfahren der Anwendung Dispatcher auch die Anwendung herunter? –

+0

Ich habe dafür eine einfache WPF-Testanwendung erstellt. Um Ihren Code zu simulieren, habe ich: 'Thread t = neuer Thread (neuer ThreadStart (delegate() {Thread.Sleep (50000);})); t.Start(); Application.Current.Dispatcher .BeginInvokeShutdown (System.Windows.Threading.DispatcherPriority.Normal); '. Der Dispatcher-Shutdown hat seinen Besitzer-Thread beendet und das Fenster geschlossen, aber * hat * den Hintergrund-Thread nicht beendet. – JustABill

+0

Zwei kleine Unterschiede: 1) Ich rufe Shutdown im zweiten Thread auf (obwohl ich durch Tests sehe, dass es keinen Unterschied macht). 2) Ich habe den zweiten Thread als Hintergrund-Thread (IsBackground = true) festgelegt. Auf diese Weise wird es auch getötet, wenn der Haupt-Thread beendet wird. –

0

By the way, Daniel - unsere Anwendung wird auf die gleiche Art und Weise aufgebaut. Es wäre interessant, zu reden und unsere Ansätze zu vergleichen.

Aber warum ich über Ihre Frage gestolpert bin, ist, dass unsere Anwendung früher Dispatcher.BeginInvokeShutdown aufgerufen hat, die mit Ausnahme von einigen Fällen gut funktionierte, in denen es nicht ordnungsgemäß beendet wurde. Als ich schließlich eine Maschine bekam, auf der dies reproduzierbar war, wurde durch den Wechsel zu Application.Current.Shutdown() das Problem behoben. Ich verstehe immer noch nicht, was das Problem war.

+0

Ich vermute, das liegt daran, dass der Aufruf von Dispatcher.BeginInvokeShutdown() alle ausstehenden Nachrichten abbricht/löscht. In meinem Fall mache ich auch eine Reihe von Aufräumarbeiten in den Fällen Window.Closing/Closed und Application.Exit (um den Win32-Teil herunterzufahren). –