2010-05-28 6 views
6

Primero un poco de fondo: tengo una aplicación WPF, que es una interfaz gráfica de usuario para una aplicación heredada de Win32. La aplicación heredada se ejecuta como DLL en un hilo separado. Los comandos que el usuario elige en la interfaz de usuario se invocan en ese "hilo heredado".Application.Current.Shutdown() vs. Application.Current.Dispatcher.BeginInvokeShutdown()

Si el "hilo heredado" finaliza, la GUI-front-end ya no puede hacer nada útil, por lo que debo cerrar la aplicación WPF. Por lo tanto, al final del método del hilo, llamo al Application.Current.Shutdown().

Como no estoy en el hilo principal, necesito invocar este comando. Sin embargo, luego noté que Dispatcher también tiene BeginInvokeShutdown() para cerrar el despachador. Así que mi pregunta es: ¿Cuál es la diferencia entre la invocación de

Application.Current.Shutdown(); 

y llamando

Application.Current.Dispatcher.BeginInvokeShutdown(); 

Respuesta

7

he hecho un poco más pruebas, y ahora creo que sé las diferencias:

1) Como se indica en la página de MSDN, BeginInvokeShutdown, además de apagar el despachador, también se borra/aborta su cola. Shutdown primero maneja todos los artículos en la cola del despachador.

Una vez que comienza el proceso de apagado, se cancelan todos los elementos de trabajo pendientes en la cola.

2) En una aplicación puedo manejar el evento Application.Exit. Este evento se dispara cuando llamo a Shutdown, ¡pero NO se dispara cuando llamo a BeginInvokeShutdown! Lo mismo se aplica a Window.Closing y Window.Closed.

En cuanto a las similitudes, en ambos casos se sale del hilo principal. Dependiendo de otros subprocesos en ejecución, esto también cierra el proceso: los subprocesos que no son de fondo se ejecutan hasta su finalización antes de que el proceso finalice.

A continuación es mi código de prueba. Comentario uno u otro método de llamada en 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()

Parece que esto es sólo una colisión de la terminología. BeginInvokeShutdown apaga el despachador , su aplicación puede, en teoría, seguir viviendo después (aunque sin un despachador, sería bastante limitado). Shutdown sin embargo, realmente sale de su aplicación, que es lo que desea.

+0

Bueno, esa es precisamente la pregunta que no se responde en la documentación: ¿apagar el despachador de la aplicación también cierra la aplicación? –

+0

Creé una aplicación de prueba WPF simple para esto. Para simular su código, lo hice: 'Thread t = new Thread (new ThreadStart (delegate() {Thread.Sleep (50000);})); t.Start(); Application.Current.Dispatcher .BeginInvokeShutdown (System.Windows.Threading.DispatcherPriority.Normal); '. El cierre de Dispatcher eliminó el hilo del propietario y cerró la ventana, pero no * mató el hilo de fondo. – JustABill

+0

Dos pequeñas diferencias: 1) Llamo apagado en el segundo hilo (aunque a través de las pruebas puedo ver que no hace ninguna diferencia). 2) Tengo el segundo hilo configurado como hilo de fondo (IsBackground = true). De esa manera, también se mata si el hilo principal se cierra. –

0

Por cierto, Daniel - nuestra aplicación está construida de la misma manera - WPF front-end para una aplicación Win32 COM (Delphi) que se ejecuta por separado. Sería interesante hablar y comparar nuestros enfoques.

Pero por qué he tropezado con su pregunta es que nuestra aplicación solía llamar a Dispatcher.BeginInvokeShutdown, que funcionó bien con excepción de unos pocos casos en los que no finalizó correctamente. Cuando finalmente encontré una máquina reproducible, al cambiar a Application.Current.Shutdown() se solucionó el problema. Todavía no entiendo cuál fue el problema.

+0

Supongo que es porque la llamada a Dispatcher.BeginInvokeShutdown() anula/borra los mensajes pendientes. En mi caso, también hago un montón de tareas de limpieza en Window.Closing/Closed cases y Application.Exit (para cerrar la parte de Win32). –

Cuestiones relacionadas