2009-04-30 13 views
5

Sto usando un thread in background per inizializzare uno strumento via USB. L'interfaccia utente si blocca quando provo ad aprire il dispositivo. Mi aspetto che il thread in background si interrompa quando chiama Open sul dispositivo, ma non il thread dell'interfaccia utente. Sto testando questo senza interazione dell'interfaccia utente dal thread in background. Non so come risolvere il problema, ed è una domanda troppo ampia, ma forse qualcuno ha già visto qualcosa di simile prima. Non c'è niente di sbagliato con l'interoperabilità ActiveX, per quanto ne so, il dispositivo funziona correttamente. Questo è l'approccio generale:Come può un thread in background bloccare il thread dell'interfaccia utente?

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. 
      } 
     } 
    } 
} 

Modifica: Forse non chiaro cosa intendevo. Con "appendere" dovrei dire "si blocca momentaneamente".

risposta

3

Il misuratore richiede l'esecuzione in uno STA? La chiamata a Open() viene effettivamente reinviata al thread dell'interfaccia utente per questo motivo?

È possibile verificare ciò è vero osservando il thread di chiamata del thread UI bloccato nel debugger.

+0

L'interfaccia utente si blocca solo per un secondo e non so come rompere nel debugger in questo caso. Ma mi hai dato l'idea di inserire la "nuova riga FancyVoltmeter()" nel gestore di thread "UpdateMeter". L'interfaccia utente non si blocca più e questo è molto interessante. –

0

Suggerirei di racchiudere la chiamata a meter.open() in un metodo separato e chiamare tale metodo dal metodo updateMeter() utilizzando il costrutto Invoke() o BeginInvoke() sul modulo o sul controllo padre. In questo modo eseguirai di nuovo l'azione sul thread dell'interfaccia utente e dovresti eseguirlo con garbo. Spero che aiuti.

+0

Ho appena provato questo e si blocca ancora la finestra principale durante la chiamata aperta. Ho provato MethodInvoker con questo: var hwnd = Process.GetCurrentProcess(). MainWindowHandle; mainWnd = Control.FromHandle (hwnd); if (mainWnd! = Null) mainWnd.Invoke (metodo); –

+0

Non garantirebbe più o meno il comportamento esatto che si cerca di evitare nella domanda? Se la chiamata aperta richiede un po 'di tempo ed è forzata l'esecuzione sul thread dell'interfaccia utente, sicuramente l'interfaccia utente rimarrà inerte durante quel periodo? –

0

Considerare l'utilizzo di un BackgroundWorker per questa attività.

+0

Ho provato prima BackgroundWorker e l'app si bloccava periodicamente quando veniva chiamato Open. L'istanziazione del controllo ActiveX all'interno del thread di lavoro è l'unica cosa che funziona, finora. –

2

Quanto tempo impiega l'istanziazione del FancyVoltmeter? Potrebbe essere che non è il metodo Open che causa il blocco dell'interfaccia utente, ma la creazione dell'oggetto COM (che è fatto sul thread dell'interfaccia utente)?

Se ciò si verifica, spostare la creazione di questo oggetto sul nuovo thread di lavoro separato dovrebbe risolvere il problema.

Edit: ho visto ora che hai già trovato questo fuori nel tuo commento a Michael ...

Problemi correlati