2010-05-28 10 views
6

D'abord un peu d'arrière-plan: J'ai une application WPF, qui est une interface graphique d'une application Win32 héritée. L'application héritée s'exécute en tant que DLL dans un thread distinct. Les commandes que l'utilisateur choisit dans l'interface utilisateur sont appelées sur ce "thread hérité". Si le "thread hérité" se termine, l'interface graphique ne peut plus rien faire d'utile, j'ai donc besoin de fermer l'application WPF. Par conséquent, à la fin de la méthode du fil, j'appelle Application.Current.Shutdown().Application.Current.Shutdown() par rapport à Application.Current.Dispatcher.BeginInvokeShutdown()

Puisque je ne suis pas sur le thread principal, j'ai besoin d'invoquer cette commande. Cependant, j'ai remarqué que le Dispatcher a également BeginInvokeShutdown() pour arrêter le répartiteur. Donc, ma question est: Quelle est la différence entre l'invocation

Application.Current.Shutdown(); 

et appeler

Application.Current.Dispatcher.BeginInvokeShutdown(); 

Répondre

7

J'ai fait quelques tests plus, et maintenant je pense que je connais les différences:

1) Comme il est indiqué dans la page MSDN, BeginInvokeShutdown, en plus d'arrêter le Dispatcher, efface également/avorte sa file d'attente. Shutdown traite d'abord tous les éléments de la file d'attente Dispatcher. Une fois le processus d'arrêt lancé, tous les éléments de travail en attente dans la file d'attente sont abandonnés. 2) Dans une application, je peux gérer l'événement Application.Exit. Cet événement est déclenché quand j'appelle Shutdown, mais pas déclenché quand j'appelle BeginInvokeShutdown! La même chose s'applique à Window.Closing et Window.Closed. En ce qui concerne les similitudes, dans les deux cas, le thread principal est quitté. En fonction des autres threads en cours d'exécution, cela interrompt également le processus: les threads non-background sont exécutés jusqu'à la fin du processus.

Voici mon code de test. Commentaire un ou l'autre appel de méthode dans Application_Startup:

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()

Il semble que ce soit juste une collision de la terminologie. BeginInvokeShutdown ferme ce répartiteur , votre application peut en théorie continuer à vivre après (bien que sans un répartiteur, ce serait assez limité). Shutdown quitte cependant votre application, ce qui est ce que vous voulez.

+0

Eh bien, c'est précisément la question à laquelle il n'y a pas de réponse dans la documentation: Est-ce que l'arrêt de l'expéditeur de l'application interrompt également l'application? –

+0

J'ai construit une application de test WPF simple pour cela. Pour simuler votre code, j'ai fait: 'Thread t = new Thread (nouveau ThreadStart (delegate() {Thread.Sleep (50000);})); t.Start(); Application.Current.Dispatcher .BeginInvokeShutdown (System.Windows.Threading.DispatcherPriority.Normal); '. L'arrêt de Dispatcher a tué son thread propriétaire et a fermé la fenêtre, mais n'a pas * tué * le thread d'arrière-plan. – JustABill

+0

Deux petites différences: 1) J'appelle l'arrêt dans le deuxième thread (bien que grâce à des tests, je peux voir que cela ne fait aucune différence). 2) J'ai le second thread défini comme thread d'arrière-plan (IsBackground = true). De cette façon, il est également tué si le thread principal se ferme. –

0

Par ailleurs, Daniel - notre application est construite de la même manière - WPF frontal à une application COM (Delphi) Win32 en cours d'exécution séparément. Il serait intéressant de parler et de comparer nos approches.

Mais pourquoi je suis tombé sur votre question est que notre application appelait à Dispatcher.BeginInvokeShutdown, qui a bien fonctionné à l'exception de quelques cas où il ne s'est pas terminé correctement. Quand j'ai finalement mis la main sur une machine sur laquelle cela était reproductible, passer à Application.Current.Shutdown() a résolu le problème. Je ne comprends toujours pas quel était le problème.

+0

Je suppose que c'est parce que l'appel à Dispatcher.BeginInvokeShutdown() annule/efface tous les messages en attente. Dans mon cas, je fais aussi un tas de nettoyage dans le Window.Closing/Closed cases et Application.Exit (pour arrêter la partie Win32). –

Questions connexes