2009-04-30 13 views
5

Estoy usando un hilo de fondo para inicializar un instrumento a través de USB. La IU se bloquea cuando intento abrir el dispositivo. Esperaría que el hilo de fondo se detenga al llamar a Abrir en el dispositivo, pero no al hilo de la interfaz de usuario. Estoy probando esto sin interacción UI del hilo de fondo. No sé cómo solucionar el problema, y ​​es una pregunta demasiado amplia, pero tal vez alguien haya visto algo como esto antes. No hay nada malo con la interoperabilidad de ActiveX hasta donde yo sé, el dispositivo funciona correctamente. Este es el enfoque general:¿Cómo puede un hilo de fondo colgar el hilo de la interfaz de usuario?

using System; 
using FancyVoltmeterLibrary; 

namespace SOQuestion 
{ 
    public class MeterClass 
    { 
     private FancyVoltmeter meter; 
     private Thread meterThread; 

     public MeterClass() 
     { 
      // Create instance of ActiveX/COM object. 
      meter = new FancyVoltmeter(); 

      meterThread = new Thread(UpdateMeter); 
      meterThread.Name = "Meter Thread"; 
      meterThread.Priority = ThreadPriority.Normal; 
      meterThread.IsBackground = true; 
      meterThread.Start(); 
     } 

     private void UpdateMeter() 
     { 
      while(true) 
      { 
       Thread.Sleep(1000); 
       if(!meter.IsOpen()) 
       { 
        // Meter may be powered off here. 
        // The call to Open takes about 1 second. 
        // UI hangs during the call??? 
        meter.Open(); 
       } 
       // code to read meter goes here. 
      } 
     } 
    } 
} 

Editar: Quizás no sea claro lo que quise decir. Por 'colgar' debería decir 'se congela momentáneamente'.

Respuesta

3

¿Requiere el medidor correr en una STA? ¿Es la llamada a Open() en realidad reorganizada de nuevo al subproceso de interfaz de usuario por este motivo?

Puede verificar esto al mirar la pila de llamadas de la hebra de interfaz de usuario colgada en el depurador.

+0

La interfaz de usuario se congela sólo por un segundo y no sé cómo romper en el depurador en este caso. Pero me dio una idea para poner la 'nueva línea FancyVoltmeter()' en el manejador de subprocesos 'UpdateMeter'. La IU ya no se congela, y esto es muy interesante. –

0

Le sugiero que complete la llamada a meter.open() en un método separado, y llame a ese método desde el método updateMeter() usando Invoke() o BeginInvoke() construir en el formulario o control principal. Al hacer esto, la acción volverá a colocarse en el subproceso de la interfaz de usuario y se ejecutará correctamente. Espero que esto ayude.

+0

Acabo de probar esto y todavía se congela la ventana principal durante la llamada abierta. Intenté MethodInvoker con esto: var hwnd = Process.GetCurrentProcess(). MainWindowHandle; mainWnd = Control.FromHandle (hwnd); if (mainWnd! = Null) mainWnd.Invoke (método); –

+0

¿No garantizaría eso más o menos el comportamiento exacto que se intenta evitar en la pregunta? Si la llamada abierta tarda un rato y se fuerza a ejecutar en el hilo de la interfaz de usuario, seguramente la interfaz de usuario permanecerá en respuesta durante ese tiempo? –

0

Considere usar un BackgroundWorker para esta tarea.

+0

Probé BackgroundWorker antes y la aplicación todavía se congelaba periódicamente cuando se llamaba Open. Instanciar el control ActiveX dentro del subproceso de trabajo es lo único que funciona, hasta ahora. –

2

¿Cuánto tiempo demora la creación de instancias del FancyVoltmeter? ¿Podría ser que no es el método Open el que causa la congelación de la UI, sino la creación del objeto COM (que se realiza en el hilo de UI)?

Si ese es el caso, mover la creación de este objeto para que ocurra en el nuevo subproceso de trabajo independiente debería solucionar el problema.

Editar: vi ahora que ya ha encontrado esto en su comentario a Michael ...

Cuestiones relacionadas