2010-07-20 11 views

risposta

14

utilizzare il metodo OnProgressChanged() dello BackgroundWorker per segnalare lo stato di avanzamento e iscriversi allo ProgessChangedEvent di BackgroundWorker per aggiornare i progressi nella GUI.

La classe di copia conosce BackgroundWorker e si abbona a ProgressChanged. Espone anche un proprio evento ProgressChanged generato dal gestore eventi per l'evento ProgressChanged dell'operatore in background. Infine il tuo Form si abbona all'evento ProgressChanged della classe di copia e visualizza l'avanzamento.

Codice:

public class CopySomethingAsync 
{ 
    private BackgroundWorker _BackgroundWorker; 
    public event ProgressChangedEventHandler ProgressChanged; 

    public CopySomethingAsync() 
    { 
     // [...] create background worker, subscribe DoWork and RunWorkerCompleted 
     _BackgroundWorker.ProgressChanged += HandleProgressChanged; 
    } 

    private void HandleProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     if (ProgressChanged != null) 
      ProgressChanged.Invoke(this, e); 
    } 
} 

Nel modulo sufficiente registrarsi al ProgressChanged caso di CopySomethingAsync e visualizzare lo stato di avanzamento.

+0

Come esporre l'evento ProgressChanged al modulo? – Martijn

+0

Ho appena aggiornato la mia risposta per dimostrarlo. – andyp

+0

questa è una risposta meravigliosa e assolutamente utile, grazie mille! –

8

Tutto quello che c'è da sapere sul BackgroundWorker è in msdn.

Come dice l'articolo:

Per ricevere notifiche di aggiornamenti sui progressi, gestire l'evento ProgressChanged.


Aggiornamento:

Letta domande supplementari di Martijn, e dato che ha una classe che fino a quel momento ha fatto il suo lavoro, presumibilmente sul filo primo piano, mi piacerebbe aggiungere il seguente:

  • La classe operaia è responsabile del lavoro, quindi ha anche la responsabilità di riferire sui suoi progressi. Il fatto che generi una sottofondo per fare il lavoro non è la preoccupazione del Form.

  • Quindi, sarei propenso a impostare la classe sul BGW e gestire i suoi eventi ProgressChanged, quindi generare i propri eventi (sul thread in primo piano) a cui il modulo stesso potrebbe quindi iscriversi. Faccio un sacco di codice WinForms usando questa tecnica e funziona perfettamente.

L'alternativa sarebbe quella di esporre il BGW come una proprietà pubblica della classe lavoratrice, e hanno la forma di gestire direttamente i suoi eventi. Ma non mi piace così tanto, poiché rende la forma dipendente dall'implementazione della classe operaia. Questa è generalmente una brutta cosa.

+0

quindi devo aggiungere una proprietà di fondo pubblico nel mio classe e il modulo deve registrarsi all'evento progresschanged? – Martijn

2

Viene eseguito tramite il metodo di istanza ReportProgress dell'oggetto BackgroundWorker corrente. Il modulo deve essere iscritto all'evento ProgressChanged.

MSDN ha un piccolo esempio qui: http://msdn.microsoft.com/en-us/library/waw3xexc%28v=VS.100%29.aspx

+0

In che modo il mio modulo si iscrive all'evento ProgressChanged? – Martijn

+0

'backgroundWorker1.ProgressChanged + = new ProgressChangedEventHandler (backgroundWorker1_ProgressChanged);' dove 'backgroundWorker1_ProgressChanged' è il nome del metodo di gestione degli eventi, prototipato dal delegato' ProgressChangedEventHandler'. – Andreas

+0

Non capisco, mi dispiace. Non vedo ancora come il mio Form possa registrarsi all'evento 'ProgressChanged'. Nel tuo caso c'è un metodo ('backgroundWorker1_ProgressChanged') che gestisce l'evento. Ma la mia forma ha bisogno di gestire l'evento, non la mia classe .. – Martijn

1

chiamata nella classe

backgroundWorker.ReportProgress(i++); 

su un gestore di moduli un evento

//declare progressBar1 in the form and set range 
// progressBar1.Minimum = 0; 
//progressBar1.Maximum = 100; 
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     //show progress bar 

    } 
+0

In questo caso, come esporre l'evento ProgressChanged nella mia classe? – Martijn

+0

Darei semplicemente alla tua classe un evento che viene generato ogni volta che viene generato l'evento ProgressChanged di BackgroundWorker. Il tuo evento avrebbe la stessa firma di quella di BackgroundWorker. – andyp

+0

Si ottiene il valore passato a 'ReportProgress' dal campo dell'istanza' ProgressPercentage' del 'ProgressChangedEventArgs' passato, ad esempio progressBar1.Value = e.ProgressPercentage;'. – Andreas

Problemi correlati