2012-05-04 10 views
13

Vedo molti thread su google/qui su AGGIORNAMENTO di un elemento dell'interfaccia utente da un altro thread.È possibile accedere agli elementi dell'interfaccia utente da un altro thread? (non impostato)

Cosa succede se voglio solo ottenere il valore di una casella di controllo?

Sono in grado di farlo senza dover fare nulla di speciale?

+0

è possibile utilizzare i delegati per farlo – jorne

+4

@CodeCaster Solo provando e vedendo ciò che funziona generalmente non si ottiene codice thread-safe. – hvd

+1

@hvd: Ma soddisfa tutte le domande poste _qui_. –

risposta

18

Modifica: Sembra che devo riprendere ciò che ho scritto prima. Provato il seguente:

Aggiunto una casella di testo chiamato myTextBox e ha cercato di recuperare il valore della proprietà Text:

Thread t = new Thread(
    o => 
    { 
     Thread.Sleep(2000);      
     string value = myTextBox.Text; 
     Thread.Sleep(2000); 
    }); 
t.Start(); 

E sembra che l'applicazione (WPF) si blocca dopo 2 secondi. Utilizzando il dispatcher funziona:

Thread t = new Thread(
    o => 
    { 
     Thread.Sleep(2000); 
     myTextBox.Dispatcher.BeginInvoke(
      (Action)(() => { string value = myTextBox.Text; })); 
     Thread.Sleep(2000); 
    }); 
t.Start(); 

Pertanto, è ancora necessario passare attraverso il filo dispatcher durante la lettura dei valori di componenti GUI, almeno in WPF.

Seconda modifica: Questo migliora. Apparentemente ripetere l'esperimento per il classico WinForms rivela che funziona per leggere la proprietà Text senza utilizzare Invoke/BeginInvoke. Abbastanza interessante, sembra che anche l'impostazione della proprietà funzioni bene (senza invocare), anche se scommetto che non è thread-safe e l'app non si lamenta per qualche motivo.

Bottom line: E 'una buona idea, in ogni caso di utilizzare il dispatcher quando interagisce con componenti GUI da altri thread, in quanto garantisce la lettura/scrittura sono serializzati ad un singolo thread e così non avete thread-sicurezza problemi.

+0

+1 per pubblicare l'esperimento. –

+0

"l'app non si lamenta" -> In esecuzione in modalità di rilascio, forse? –

+0

@ Holen Holterman: ho provato sia Release che Debug e non riesco a notare alcuna differenza. – Tudor

0

leggere semplicemente il valore come si fa normalmente. Solo per aggiornare il controllo, è necessario passare al thread GUI.

+1

Probabilmente funziona con CheckBox.Checked perché è una proprietà booleana. Come altri hanno pubblicato, ottenere textbox.Text è molto più rischioso. –

2

Si potrebbe ma rigorosamente non sarebbe thread-safe. Ad esempio se la proprietà Ottieni codice consisterà in più operazioni, il thread dell'interfaccia utente potrebbe agire nel frattempo, a metà strada durante l'operazione Get, causando risultati imprevisti.

7

È possibile accedere agli elementi dell'interfaccia utente da un altro thread? (non impostato)?

No.

Ecco l'affare. Gli elementi dell'interfaccia utente hanno requisiti di affinità della filettatura molto rigidi. Ciò significa che puoi accedere all'elemento solo dal thread che lo ospita. Questo include tutti i tipi di accesso, comprese le letture semplici.

Può funzionare bene per getter di proprietà semplici, ma la sua sicurezza percepita sarebbe un risultato accidentale del modo in cui è stato implementato quel particolare controllo. Poiché Control istanze hanno affinità di thread potrebbero potenzialmente usare filo tecniche di memorizzazione locali per salvare una parte del loro stato che, naturalmente, non sarebbe compatibile con filetto differente. O se il valore che stai cercando di leggere è in uno stato semi-cotto? Non ci sarebbe modo di sincronizzare l'accesso a quella lettura dal momento che la scrittura potrebbe verificarsi all'interno del codice su cui non si ha alcun controllo.Eppure questo sta ignorando i sottili problemi di barriera della memoria che possono sorgere.

Anche in questo caso, se sembra funzionare, digerirlo come un incidente. Accedere agli elementi dell'interfaccia utente da un thread rispetto a quello che li ospita è una ricetta per il disastro. Le cose potrebbero fallire in modo imprevedibile e spettacolare.


Ci sono pochissime eccezioni a questa regola. L'utilizzo dei metodi ISynchronizeInvoke è una tale eccezione.

Problemi correlati