Perché ottengo questo errore: “Operazione cross-thread non valida: Controllo lbFolder accessibili da un thread diverso dal thread su cui è stato creato.”?

Questo mi sconcerta, forse qualcuno può illuminare la luce dell’istruzione sulla mia ignoranza. Questo è in un’app windows C #. Sto accedendo al contenuto di una listbox da una discussione. Quando cerco di accedervi in ​​questo modo

prgAll.Maximum = lbFolders.SelectedItems.Count; 

Ottengo l’errore Comunque, ecco la parte che non capisco. Se commento questa linea, la riga successiva

 foreach (string dir in lbFolders.SelectedItems) 

esegue bene.

Modifica: Come al solito, le mie capacità comunicative sono carenti. Permettimi di chiarire.

So che l’accesso agli elementi della GUI da thread diversi da quelli su cui sono stati creati causa problemi. So che il modo giusto per accedervi è tramite delegato.

La mia domanda era principalmente questa: perché posso accedere e scorrere l’object SelectedItems bene, ma quando provo a ottenere (non impostato) la proprietà Count di esso, esplode.

 prgAll.Maximum = lbFolders.SelectedItems.Count; 

Su quella linea si esegue un compito ( set / add ), che per impostazione predefinita non è thread-safe.

Nella seconda riga è solo un’operazione get , in cui la sicurezza del thread non ha importanza.

EDIT: non intendo l’accesso all’elemento prgAll.

L’accesso alla proprietà Count modifica lo stato interno della raccolta interna di ListBox, motivo per cui genera l’eccezione.

Non è ansible accedere agli elementi della GUI da un thread separato. Utilizzare un delegato per apportare la modifica.

per esempio.

 lblStatus.Invoke((Action)(() => lblStatus.Text = counter.ToString())); 

o più vecchia scuola:

 lblTest.Invoke((MethodInvoker)(delegate() { lblTest.Text = i.ToString(); })); 

Ho un post sul blog su come farlo in tutte le versioni .Net qui .

La proprietà Count di SelectedItems non è thread-safe, quindi non puoi usarla cross-thread.

Stai cercando di scrivere su un controllo da un thread diverso dal thread principale. Utilizzare Invoke o BeginInvoke.

 void SetMax() { if (prgAll.InvokeRequired) { prgAll.BeginInvoke(new MethodInvoker(SetMax)); return; } prgAll.Maximum = lbFolders.SelectedItems.Count; } 

Non è ansible toccare un object GUI da un thread che non è il thread della GUI principale. Vedi qui per maggiori dettagli e la soluzione.

Perché hai creato un controllo in un thread e stai provando a raggiungerlo da un altro. Chiama la proprietà InvokeRequired come mostrato qui:

 private void RunMe() { if (!InvokeRequired) { myLabel.Text = "You pushed the button!"; } else { Invoke(new ThreadStart(RunMe)); } } 

Prova questo:

 private delegate void xThreadCallBack(); private void ThreadCallBack() { if (this.InvokeRequired) { this.BeginInvoke(new xThreadCallBack(ThreadCallBack)); } else { //do what you want } } 

Però, la risposta con l’espressione lambda sarebbe sufficiente.