2011-02-25 15 views
7

Estoy mostrando una animación mientras mi control está cargando los datos. Cuando termina el hilo, oculto la animación y muestro el control. Así que estoy ejecutando el código de un hilo:Control.Invoke() bloquea la aplicación

protected void InvokeEnableBackControl() 
{ 
    if (this.InvokeRequired) 
    {     
     this.Invoke(new OpHandler(EnableBackControl)); 
    } 
    else 
    { 
     EnableBackControl(); 
    } 
} 

A veces, cuando yo haga este código, el hilo principal se colgaron en el siguiente código:

protected virtual void EnableBackControl() 
{ 
    if (overlayAnimation.TargetControl != null) 
    { 
     overlayAnimation.TargetControl.BringToFront(); 
    } 

    overlayAnimation.SendToBack(); 
    overlayAnimation.Enabled = false; 
    overlayAnimation.Visible = false;      

}

I' No estoy seguro si está colgado configurando la propiedad Enable o Visible. ¿Conoces alguna circunstancia que pueda entregar la aplicación llamando a estas propiedades desde Control.Invoke?

+0

¿Existe un patrón discernible a los tiempos en que se cuelga? –

+0

@No, solo "a veces". Molesto. –

+0

Documente la sentencia * exact * que cuelga, publique el seguimiento de la pila. –

Respuesta

3

Ejecute la depuración, haga que la aplicación cuelgue y luego pause la depuración en Visual Studio e inspeccione los subprocesos.

+0

¿Qué tipo de respuesta es esta? Adjunté el proceso con el depurador, me detuve e inspeccioné los hilos. Esta es la razón por la que sé que el hilo está en el primer bloque de código, y el hilo principal está en el segundo. –

+0

@ Daniel Peñalba esta es una especie de solución que me ayuda. Porque cuando haces esto puedes ver las líneas exactas donde se cuelga el hilo. – Andrey

+0

Lo hice. La línea resaltada cuando rompo todos los hilos es 'overlayAnimation.Visible = false;' pero generalmente Visual Studio (casi 2003) se detiene en la línea anterior. Solo a veces, esta es la razón por la que no estoy seguro de si esa línea o la anterior. –

7

me he encontrado problemas antes cuando estoy en la ejecución de .Invoke un subproceso en segundo plano mientras mi hilo principal todavía está ocupado - esto da la impresión de que la aplicación se cuelga, porque el .Invoke simplemente se sienta allí, esperando que el hilo principal responda que está prestando atención. Posibles causas:

  • Su hilo principal está bloqueada esperando algo
  • Su forma principal en la actualidad con un diálogo modal hacia arriba, por lo que no está escuchando a las nuevas solicitudes
  • Su hilo principal está girando, o bien comprobar continuamente si algo está terminado o haciendo un nuevo trabajo. En mi caso, el hilo principal pasó el primer minuto haciendo girar los hilos de fondo en un bucle cerrado, por lo que no estaba escuchando ninguno. Invoque las solicitudes de los hilos de fondo.

Cuando conecte el depurador, preste especial atención a lo que está haciendo su thread de MessagePump de control principal - sospecho que su falta de atención es la causa de su problema. Si identifica que hay un círculo cerrado en su hilo principal que no responde, intente insertar un .DoEvents en el ciclo, lo que pausará la ejecución y forzará al hilo principal a vaciar la bomba de mensajes y enrutar las solicitudes pendientes.

+0

Gracias, ese era mi caso, y Application.DoEvents() hizo el truco. – Tate

0

Lo que descubrí es que el dibujo/pintura real de los controles puede ser bastante lento, especialmente si usted tiene muchos de ellos y/o usa doble almacenamiento en búfer para una actualización sin problemas. Estaba usando BeginInvoke para actualizar un control de vista de lista a partir de los datos que recibía de un socket. A veces las actualizaciones estaban sucediendo tan rápido que congelaba la aplicación. Lo resolví escribiendo todo lo que recibí en los sockets async receive en una cola, y luego en un hilo separado dequeueing los datos y usando BeginUpdate y EndUpdate en la vista de lista y haciendo todas las actualizaciones pendientes en el medio. Esto eliminó una tonelada de redibujado extra e hizo que la aplicación fuera mucho más receptiva.

0

Usted tiene que usar BeginInvoke inested Invoke ver este Link

Cuestiones relacionadas