.net - validacion - Cómo abrir un formulario en un hilo y obligarlo a permanecer abierto
validar formulario html5 (6)
Creo que solo llamar a ShowDialog en lugar de Show ayudará. El problema parece ser que el hilo termina justo después de llamar a Show, luego de eso, se recoge la basura del Formulario. ShowDialog detendrá el hilo pero aún ejecutará los eventos de forma en él para que el hilo se siga ejecutando hasta que se cierre el formulario.
Normalmente lo haría al revés. Ejecute el formulario en el subproceso de inicio e inicie los subprocesos de fondo cuando desee iniciar tareas de fondo de larga ejecución.
También leí tu otra pregunta, pero no pude entender qué estás tratando de hacer. MVP-architecture no requiere que ejecute su lógica comercial en diferentes hilos. El subprocesamiento múltiple es difícil de hacer, así que solo usaría varios subprocesos si realmente los necesitara.
Todavía estoy teniendo problemas para descubrir cómo crear formas de triunfo en un subproceso de IU separado que discutí aquí .
Al tratar de resolver esto escribí el siguiente programa de prueba simple. Simplemente quiero que abra un formulario en un subproceso separado denominado "subproceso de interfaz de usuario" y mantenga el subproceso en ejecución siempre que el formulario esté abierto y permita al usuario interactuar con el formulario (el spinning es una trampa). Entiendo por qué no funciona lo siguiente y el hilo se cierra de inmediato, pero no estoy seguro de qué debo hacer para solucionarlo.
using System;
using System.Windows.Forms;
using System.Threading;
namespace UIThreadMarshalling {
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var tt = new ThreadTest();
ThreadStart ts = new ThreadStart(tt.StartUiThread);
Thread t = new Thread(ts);
t.Name = "UI Thread";
t.Start();
Thread.Sleep(new TimeSpan(0, 0, 10));
}
}
public class ThreadTest {
Form _form;
public ThreadTest() {
}
public void StartUiThread() {
_form = new Form1();
_form.Show();
}
}
}
Creo que su problema es con este pensamiento: "abrir un formulario en un hilo separado llamado ''UI thread''"
La forma en que funciona Windows es así (por ejemplo, Vista puede cambiar algunas de estas realidades):
Hay un hilo importante llamado " Hilo principal " o el " Hilo de UI ". Este hilo es el que procesa los mensajes de Windows , como "hey el mouse hizo clic en este píxel".
Estos mensajes entran en una cola y el hilo principal los procesa cuando no está ocupado haciendo otra cosa .
Por lo tanto, si realiza una función, llame a foo () en el hilo principal, si lleva mucho tiempo, no se procesan los mensajes de Windows durante ese tiempo y, por lo tanto, no puede haber interacción del usuario.
El hilo principal también pinta la interfaz de usuario en la pantalla, por lo que foo () de larga ejecución también detendrá la aplicación de la pintura.
Todos los otros hilos además de este hilo principal sagrado y especial son hilos de trabajo ronco. Estos subprocesos de trabajo pueden hacer cosas, pero nunca pueden interactuar directamente con la interfaz de usuario.
Esta realidad causa dos problemas:
DESCONECTARSE DEL HILO PRINCIPAL: dado que no desea que foo () de larga ejecución detenga toda la interacción del usuario, debe enviar ese trabajo a un hilo de trabajo.
VOLVER AL HILO PRINCIPAL: Cuando se complete el funcionamiento lento de foo (), probablemente desee notificar al usuario haciendo algo en la interfaz de usuario, pero no puede hacer eso en un hilo de trabajo, por lo que debe "volver" al Hilo principal.
Así que creo que su problema en el programa anterior es muy general: su objetivo es incorrecto, porque se supone que no se puede llamar a _form.Show () en ningún hilo, excepto el hilo principal sagrado.
En un nuevo hilo, llame a Application.Run pasando el objeto de formulario, esto hará que el hilo ejecute su propio bucle de mensaje mientras la ventana está abierta.
Luego puede llamar .Únete a ese hilo para hacer que el hilo principal espere hasta que finalice el hilo de la interfaz de usuario, o utiliza un truco similar para esperar a que se complete el hilo.
Ejemplo:
public void StartUiThread()
{
using (Form1 _form = new Form1())
{
Application.Run(_form);
}
}
No puede abrir un formulario GUI en ningún hilo, ya que le faltará un mensaje de bomba. Debe iniciar explícitamente una bomba de mensajes en ese subproceso invocando Application.Run () en un método de subproceso. Otra opción es llamar a DoEvents () en un bucle, si necesita hacer otra cosa, porque después de Application.Run () ese hilo esperará a un usuario a cerrar un formulario en ese punto de ejecución.
private void button1_Click(object sender, EventArgs e)
{
var t = new Thread(RunNewForm);
t.Start();
}
public static void RunNewForm()
{
Application.Run(new Form2());
}
En lugar de llamar a show () en el formulario que se ejecutará en el formulario y luego cerrar al final de la ejecución del subproceso dentro de la función StartUiThread (), puede bloquear el subproceso hasta que el formulario se detenga dentro del método ya que simplemente está bloqueando el otro hilo. Ex:
public void StartUiThread() {
_form = new Form1();
_form.ShowDialog(); //Change Show() to ShowDialog() to wait in thread
}
Esto causará que el nuevo subproceso espere hasta que se cierre el diálogo. No sé si esto resolverá tus problemas, pero resolvió el mío.