2009-02-20 14 views
26

Qual è il modo migliore per aggiornare un'etichetta su un'applicazione Windows Form durante l'elaborazione?Aggiorna etichetta durante l'elaborazione in Windows Form

Ho un ciclo che esegue l'elaborazione su file nel sistema dell'utente quando l'utente fa clic su un pulsante.

foreach (System.IO.FileInfo f in dir.GetFiles("*.txt")) 
{ 
    // Do processing 
    // Show progress bar 
    // Update Label on Form, "f.Name is done processing, now processing..." 
} 

Quale sarebbe un codice di esempio?

Che cosa si chiama esattamente? È threading o delegati?

risposta

48

Una soluzione rapida per voi sarebbe:

Label1.Text = f.Name + " is done processing, now processing..."; 
Label1.Refresh(); 

si vuole veramente evitare DoEvents, altrimenti avrete problemi se l'utente preme ripetutamente i pulsanti sul modulo.

13

Si dovrebbe di farlo da un altro thread, e quindi l'aggiornamento del thread dell'interfaccia utente da questo thread. Stai bloccando ulteriori elaborazioni eseguendo questo lavoro sul thread dell'interfaccia utente.

Se può non spostare questo codice al thread UI, allora si potrebbe sempre chiamare Application.DoEvents, ma io fortemente suggerire di esplorare queste opzioni prima:

+1

Sono d'accordo con questo, specialmente per BackgroundWorker. Lo uso spesso me stesso.Background I collaboratori rendono le operazioni multi-threading così semplici e facili! – Keithius

13

Avrete bisogno di ottenere i dati da un thread all'altro. Questo può essere fatto in un paio di modi ...

In primo luogo, il tuo thread "di sfondo" può aggiornare una specie di variabile di stringa "CurrentStatus" che cambia mentre procede. È quindi possibile inserire un timer nel modulo in modo da acquisire la variabile CurrentStatus e aggiornare l'etichetta con esso.

In secondo luogo, è possibile semplicemente richiamare l'operazione dal thread in background al thread dell'interfaccia utente con un delegato che utilizza la proprietà InvokeRequired del controllo etichetta. Così, per esempio ...

private delegate void UpdateStatusDelegate(string status); 
private void UpdateStatus(string status) 
{ 
    if (this.label1.InvokeRequired) 
    { 
     this.Invoke(new UpdateStatusDelegate(this.UpdateStatus), new object[] { status }); 
     return; 
    } 

    this.label1.Text = status; 
} 

È possibile chiamare che UpdateStatus() il metodo da qualsiasi thread (UI o di fondo), ed è in grado di rilevare se o non ha bisogno di richiamare l'operazione sul thread dell'interfaccia utente principale (e se è così, lo fa).

Per impostare in realtà il filo, è possibile farlo in questo modo:

private void StartProcessing() 
    { 
     System.Threading.Thread procThread = new System.Threading.Thread(this.Process); 

     procThread.Start(); 
    } 

    private void Process() // This is the actual method of the thread 
    { 
     foreach (System.IO.FileInfo f in dir.GetFiles("*.txt")) 
     { 
      // Do processing 
      // Show progress bar 
      // Update Label on Form, "f.Name is done processing, now processing..." 
      UpdateStatus("Processing " + f.Name + "...");     
     } 
    } 

Poi, quando l'utente fa clic sul pulsante "GO" sarà sufficiente chiamare StartProcessing().

+1

Deve essere la risposta perfetta. –