2013-02-15 18 views
17

Uso una scrittura di thread in un'altra classe per aggiornare un'etichetta. L'etichetta è contenuta nella classe principale di Winform.Aggiorna etichetta da un'altra filettatura

Scanner scanner = new Scanner(ref lblCont); 
scanner.ListaFile = this.listFiles; 
Thread trd = new Thread(new ThreadStart(scanner.automaticScanner)); 
trd.IsBackground = true; 
trd.Start(); 
while (!trd.IsAlive) ; 
trd.Join(); 

Come potete vedere, ho passato il riferimento dell'etichetta nel costruttore della seconda classe. Nella seconda classe (Scanner) ho un metodo chiamato "automaticScanner" che dovrebbe aggiornare l'etichetta con questo codice:

public Scanner(ref ToolStripStatusLabel _lblContatore) 
{ 
     lblCounter= _lblContatore; 
} 
Thread threadUpdateCounter = new Thread(new ThreadStart(this.UpdateCounter)); 
threadUpdateCounter.IsBackground = true; 
threadUpdateCounter.Start(); 
while (!threadUpdateCounter .IsAlive) ; 
threadUpdateCounter.Join(); 

private void AggiornaContatore() 
{ 
    this.lblCounter.Text = this.index.ToString();   
} 

Ho ricevere questo errore aggiornamento dell'etichetta:

Operazione cross-thread non valida: controllo 'Main' a cui si accede da un thread diverso dal thread creato su

Io uso .net 4 con Winform C#.

Grazie mille per le risposte.

Notizie: Il problema è questa linea:

trd.Join(); 

Questa linea di bloccare la mia GUI e l'etichetta non è stato aggiornato. Esistono metodi per controllare la fine del thread e aggiornare l'etichetta fino alla fine? Grazie

+0

ma ... la sua corretta chiamata il filo in questo modo? Thread trd = new Thread (new ThreadStart (scanner.scansioneAutomatica)); trd.IsBackground = true; trd.Start(); while (! Trd.IsAlive); trd.Join(); In questa modalità la GUI è bloccata! : S – Antonio

+0

Includi all'interno della classe il codice Azione y; e la funzione di attendere l'evento scaduto del timer vuoto privato T_Elapsed (oggetto mittente, System.Timers.ElapsedEventArgs e) { C++; // delegato è l'espressione "y =() => label1.Text = c.ToString()" label1.Invoke (y =() => label1.Testo = c.ToString()); } –

risposta

41

Non è possibile aggiornare l'interfaccia utente da nessun altro thread diverso dal thread dell'interfaccia utente. Da utilizzare per aggiornare il thread sul thread dell'interfaccia utente.

private void AggiornaContatore() 
{   
    if(this.lblCounter.InvokeRequired) 
    { 
     this.lblCounter.BeginInvoke((MethodInvoker) delegate() {this.lblCounter.Text = this.index.ToString(); ;});  
    } 
    else 
    { 
     this.lblCounter.Text = this.index.ToString(); ; 
    } 
} 

prega di passare attraverso questo capitolo e di più da questo libro per avere un quadro chiaro circa filettatura:

http://www.albahari.com/threading/part2.aspx#_Rich_Client_Applications

+0

lblCounter non contiene una definizione per InvokeRequired, lo stesso per BeginInvoke – Antonio

+0

non ho Label, ma ToolStripStatusLabel – Antonio

+0

IIRC, InvokeRequired esiste in ogni controllo, ma è PROTETTO, questo è il motivo per cui lo vedi solo in " la tua attuale classe "(es .: Form, UserControl) e tentare di accedervi su un'altra classe (es. Label, TextBox) non riesce – quetzalcoatl

10

Utilizzare MethodInvoker per aggiornare il testo dell'etichetta in un'altra discussione.

private void AggiornaContatore() 
{ 
    MethodInvoker inv = delegate 
    { 
     this.lblCounter.Text = this.index.ToString(); 
    } 

this.Invoke(inv); 
} 

Hai trovato l'errore perché il thread dell'interfaccia utente sta tenendo l'etichetta, e dal momento che si sta tentando di aggiornare attraverso un altro thread che si stanno ottenendo un'eccezione filo trasversale.

Si può anche vedere: Threading in Windows Forms

+0

la mia classe non è interfacciabile. per questo motivo this.IsDisposed non si trova .. – Antonio

+0

@Antonio, rimuovere il controllo e basta chiamarlo direttamente – Habib

+0

nel metodo avanti contatore della mia classe Scanner il metodo Invoke non è stato trovato. – Antonio