2014-07-18 15 views
8

Vorrei interrompere il mio dispatcher che è stato avviato nella main(), quando l'utente fa clic su un pulsante.Come posso uscire (arrestare) il mio Dispatcher?

private void button_start_Click(object sender, RoutedEventArgs e) 
    { 
     ... 
      Camera.EventFrame -= onFrameEventFocusCam; //unsubscribe event 

      while (!Dispatcher.HasShutdownStarted) 
      { 
       // test if Dispatcher started shutdown --> ok, it does but never finishs...! 
      } 
     ... 
    }   


    private void onFrameEventFocusCam(object sender, EventArgs e) 
    { 
     ... 

     Dispatcher.Invoke(new Action(() => 
     { 
      // Convert bitmap to WPF-Image 
      var bmp = new Bitmap(bitmap); 
      var hBitmap = bmp.GetHbitmap(); 

      System.Windows.Media.ImageSource wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
      hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); 

      image_fokus.Source = wpfBitmap; 
      image_fokus.Stretch = System.Windows.Media.Stretch.UniformToFill; 


      DeleteObject(hBitmap); 
      bitmap.Dispose(); 

     })); 
     GC.Collect(); 
    } 

Quando eseguo questo codice ottengo seguente messaggio di errore mentre è fermato nella onFrameEventFocusCam:

Error-Message: Thread was interrupted from a waiting state. 
+0

Se si interrompe il dispatcher thread principale, l'applicazione smetterà di funzionare ... è davvero quello che vuoi? Cosa stai cercando di fare esattamente? –

+0

Non mi piace interrompere il thread principale. Quello che sto cercando di fare è fermare una macchina fotografica per mostrare un'immagine dal vivo. L'applicazione dovrebbe ancora funzionare. – Norick

risposta

2

Quando si chiama BeginInvokeDispatcher, che provoca il dispatcher di chiudere in modo asincrono ; deve ancora terminare l'elaborazione del frame del dispatcher corrente prima che si chiuda. Ma dal momento che stai aspettando in un ciclo che il dispatcher si spenga, il fotogramma corrente non viene mai completato, quindi il dispatcher non può completare l'arresto. Invece, è possibile abbonarsi all'evento ShutdownFinished per rilevare quando il dispatcher si arresta.

Per quanto riguarda l'errore che stai ricevendo in onFrameEventFocusCam, penso che questo sia dovuto al fatto che il dispatcher si sta spegnendo, quindi non può elaborare il Invoke; dalla documentazione:

Una volta avviato il processo di arresto, tutti gli elementi di lavoro in sospeso nella coda vengono interrotti.

Non sono sicuro di quello che stai cercando di fare, ma spegnere il dispatcher principale è molto probabilmente non il modo per farlo, come si fermerà in modo efficace l'applicazione ...

+0

Ho cambiato il codice nel modo in cui sto usando questo: 'Camera.EventFrame - = onFrameEventFocusCam; Dispatcher.InvokeShutdown(); ' Ora il processo di spegnimento è iniziato ma non è ancora terminato. Quindi devo aspettare in un evento ShutdownFinished fino a quando non viene completato? – Norick

+0

@Norick, non chiudere il dispatcher. Non fa quello che vuoi, blocca semplicemente l'app. Annullare l'iscrizione all'evento dovrebbe essere sufficiente per interrompere la visualizzazione delle immagini. –

+0

Ho annullato l'iscrizione all'evento ma ottengo ancora lo stesso messaggio di errore. Se spengo anche il dispatcher, l'app è ancora in esecuzione, ma almeno l'evento (quasi) non si verifica più. Non capisco del tutto perché non funzioni correttamente ... – Norick

0

Per fare in modo che il dispatcher di arresto sia in esecuzione sul thread principale dell'applicazione, è necessario richiamare il ritorno dall'azione inoltrata a Dispatcher.Invoke.

+0

potresti fare un esempio per favore? – Norick

2

Non è chiaro quale fosse l'intenzione originale.

Questo codice dovrebbe bloccarsi (quasi) per sempre perché HasShutdownStarted non diventa true fino all'uscita dell'applicazione.

while (!Dispatcher.HasShutdownStarted) 
      { 
       // test if Dispatcher started shutdown --> ok, it does but never finishs...! 
      } 

Questo codice pianifica l'esecuzione del delegato sul thread dell'interfaccia utente. Sembra perfettamente a posto

private void onFrameEventFocusCam(object sender, EventArgs e) 
    { 
     ... 

     Dispatcher.Invoke(new Action(() => 
     { 
     ... 
     } 
    } 

Questo codice è potenzialmente problematico perché se DeleteObject rilascia in realtà la maniglia, che il manico può essere rilasciato due volte, una nel Delete e una volta in Dispose. Questo può buttare.

DeleteObject(hBitmap); 
bitmap.Dispose();