2009-07-10 8 views
26

Necesito crear dos (o más) ventanas WPF del mismo proceso. Pero las ventanas deben manejarse con hilos separados porque no deberían poder bloquearse entre sí. ¿Cómo hago esto?¿Cómo creo y muestro ventanas WPF en hilos separados?

En WinForms Esto se logra mediante:

  • un hilo nuevo
  • Crear un formulario desde el nuevo hilo
  • llamada Application.Run con la forma como parámetro

Pero ¿cómo hago lo mismo en WPF?

Respuesta

40

Como msdn estados:

private void NewWindowHandler(object sender, RoutedEventArgs e) 
{  
    Thread newWindowThread = new Thread(new ThreadStart(ThreadStartingPoint)); 
    newWindowThread.SetApartmentState(ApartmentState.STA); 
    newWindowThread.IsBackground = true; 
    newWindowThread.Start(); 
} 

private void ThreadStartingPoint() 
{ 
    Window1 tempWindow = new Window1(); 
    tempWindow.Show();  
    System.Windows.Threading.Dispatcher.Run(); 
} 

EDIT: esta es una respuesta de edad, pero ya que parece ser visitado a menudo, también podría pensar en las siguientes modificaciones/mejoras (no probado).

Si desea cerrar una ventana de este tipo, simplemente mantener una referencia al objeto de ventana desde el exterior de la rosca (delegado), y luego invocar estrecha en él, algo como esto:

void CloseWindowSafe(Window w) 
{ 
    if (w.Dispatcher.CheckAccess()) 
     w.Close(); 
    else 
     w.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadStart(w.Close)); 
} 

// ... 
CloseWindowSafe(tempWindow); 

Si el nuevo hilo podría llegar a ser terminado (abortada por la fuerza), en línea con la pregunta en los comentarios:

private void ThreadStartingPoint() 
{ 
    try{ 
     Window1 tempWindow = new Window1(); 
     tempWindow.Show();  
     System.Windows.Threading.Dispatcher.Run(); 
    } 
    catch(ThreadAbortException) 
    { 
     tempWindow.Close(); 
     System.Windows.Threading.Dispatcher.InvokeShutdown(); 
    } 
    //the CLR will "rethrow" thread abort exception automatically 
} 

AVISO: no hacer esto en casa, abortando hilos es (casi siempre) con las mejores prácticas. Los hilos deben manejarse con gracia mediante cualquiera de las diversas técnicas de sincronización, o en este caso, simplemente a través de un invocado window.Close()

+3

Gran ¿Cómo puedo cerrar una ventana creada de esta manera –

+0

Sé que es una vieja pregunta, pero este enfoque todavía funciona. Tengo solo un problema - lo uso para cargar la ventana, así que - mostrar la ventana de carga en un nuevo hilo -> hacer cosas -> newThread.Abort() y está bien, pero si lo vuelvo a hacer, se bloquea toda la aplicación. porque va a ejecutar el despachador de nuevo. ¿Cómo resolverlo? – MajkeloDev

+0

Hola, estaba luchando con esto también. Para mí, este [enlace] (https://dontpaniclabs.com/blog/post/2013/11/14/dynamic -splash-screens-in-wpf /) funcionado. Esto usa el ManualResetEvent-way. Hay una fuente para descargar y compruebe también (GitHub) – dba

2

Creo que encontré la respuesta. Mira la respuesta de Jon Skeet en este question.

Básicamente lo hace así en su método de inicio de la rosca:

private void ThreadStartingPoint() 
{ 
    Window1 tempWindow = new Window1(); 
    tempWindow.Show();  
    System.Windows.Threading.Dispatcher.Run(); 
} 
+0

Ooops .. hasta tarde, gracias kek444. –

1

exactamente lo que estaba buscando.

lo estoy haciendo como esto sin embargo:

App.xaml.cs

public partial class App : Application 
    { 
     protected override void OnStartup(StartupEventArgs e) 
     { 
      base.OnStartup(e); 

      Thread newWindowThread = new Thread(new ThreadStart(ThreadStartingPoint)); 
      newWindowThread.SetApartmentState(ApartmentState.STA); 
      newWindowThread.IsBackground = true; 
      newWindowThread.Start(); 

      var window = new MainWindow(newWindowThread); 
      window.DataContext = new MainWindowViewModel(window); 
      window.Show(); 
     } 

     private void ThreadStartingPoint() 
     { 
      SplashWindow tempWindow = new SplashWindow(); 
      tempWindow.Show(); 
      System.Windows.Threading.Dispatcher.Run(); 
     } 
    } 

MainWindow.Xaml.cs

public partial class MainWindow : Window 
{ 
    public MainWindow(Thread splashWindowThread) 
    { 
     InitializeComponent(); 

     MyInializaComponent(); 

     splashWindowThread.Abort(); 
    } 

//void DoStuff(){}; 
} 

necesitaba mi pantalla de bienvenida a desaparecer después de la programa ha hecho toda la carga.

9

Por lo que sea, ya que esta respuesta es el primer resultado proporcionado por Google. También me gustaría añadir lo siguiente tomado de Eugene Prystupa's Weblog:.

"Hay una captura a nuestra solución simplificada cerrar una ventana en particular no NO terminan despachador hilo de esta ventana, por lo que el hilo sigue funcionando y, tras al cerrar todas las ventanas, el proceso no finalizará y se convertirá en un proceso fantasma.[La] Solución simple (y no correcta) a esto es marcar nuestros hilos como fondo (usando thread.IsBackground = true;). Esto los obligará a terminar cuando termine el hilo de UI principal.

La implementación correcta cerrará con gracia el despachador cuando ya no sea necesario. El código siguiente es un ejemplo de una estrategia para poner fin al despachador cuando la ventana se cierra:.?"

private void OnCreateNewWindow(object sender, RoutedEventArgs e) 
{ 
    Thread thread = new Thread(() => 
    { 
     Window1 w = new Window1(); 
     w.Show(); 

     w.Closed += (sender2, e2) => 
      w.Dispatcher.InvokeShutdown(); 

     System.Windows.Threading.Dispatcher.Run(); 
    }); 

    thread.SetApartmentState(ApartmentState.STA); 
    thread.Start(); 
} 
+1

Enlace de referencia similar en el caso de que el anterior ya no funcione: [Lanzamiento de una ventana de WPF en un subproceso separado, Parte 1] (http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in -a-separate-thread-part-1 /) –

Cuestiones relacionadas