2012-05-22 11 views
5

Ho una soluzione funzionante che riporta il progresso & testo in una barra di avanzamento e un'etichetta nel modulo principale dell'applicazione. Ora ho spostato i miei metodi di lavoro in una classe perché sono accessibili su più moduli, ecc.BackgroundWorker segnala l'avanzamento da una classe esterna?

All'interno dei metodi di lavoro sono le dichiarazioni BW.ReportProgress() che restituiscono il progresso e il testo a BackgroundWorker nel modulo principale.

Per rendere meglio l'idea qui è il layout del file:

MainScreen.cs

List repSelected = new List(); 
XMLandRar xXMLandRar = new XMLandRar(); 

private void Rarbtn_Click(object sender, EventArgs e) 
     { 
      GetReps(); 

      //Run worker 
      if (!CreateRarBW.IsBusy) 
      { 
       CreateRarBW.RunWorkerAsync(); 
      } 
     } 

//Worker 
private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e) 
{ 
    xXMLandRar.RarFiles(repSelected); 
} 

//Progress reporting 
private void CreateRarBW_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    progBar.Value = e.ProgressPercentage; 
    Statuslbl.Text = e.UserState.ToString(); 
} 

Poi la mia classe appena creata che racchiude tutti i metodi di lavoro ed è quello di spingere il progresso al form principale.

XMLandRar.cs

public class XMLandRar 
{ 
    public void RarFiles(List repSelected) 
    { 
     int step = 100/repSelected.Count(); 
     int i = 0; 
     //Iterate through list and run rar for each 
     foreach (string rep in repSelected) 
     { 
      CreateRarBW.ReportProgress(i, "Raring files for " + rep); 
      DirectoryExists(rep); 
      ProcessRunner(rep); 
      i += step; 
      CreateRarBW.ReportProgress(i, "Raring files for " + rep); 
     } 
    } 
}

Il problema che sto avendo è che nella classe XMLandRar il CreateRarBW non viene riconosciuto (ovviamente) - come posso fare un ReportProgress chiamata al BW nella schermata principale dell'applicazione?

risposta

9

Creare un evento nella classe XMLandRar a cui è possibile iscriversi.

In questo modo la classe XMLandRar non ha bisogno di conoscere o preoccuparsi dell'interfaccia utente o della barra di avanzamento, si preoccupa solo di inviare un messaggio se qualcuno ascolta.E ci può essere anche più di un abbonato (diciamo se si vuole riferire al lavoratore di sfondo e un registro, forse)

Esempio:

private void Rarbtn_Click(object sender, EventArgs e) 
{ 
    GetReps(); 

    //Run worker 
    if (!CreateRarBW.IsBusy) 
    { 
     // This should be done once, maybe in the contructor. Bind to new event. 
     xXMLandRar.ReportProgress += new EventHandler<XMLandRar.ProgressArgs>(xXMLandRar_ReportProgress); 

     CreateRarBW.RunWorkerAsync(); 
    } 
} 

protected void xXMLandRar_ReportProgress(object sender, XMLandRar.ProgressArgs e) 
{ 
    // Call the UI backgroundworker 
    CreateRarBW.ReportProgress(e.Percentage, e.Message); 
} 

public class XMLandRar 
{ 
    // Event handler to bind to for reporting progress 
    public EventHandler<ProgressArgs> ReportProgress; 

    // Eventargs to contain information to send to the subscriber 
    public class ProgressArgs : EventArgs 
    { 
     public int Percentage { get; set; } 
     public string Message { get; set; } 
    } 

    public void RarFiles(List repSelected) 
    { 
     int step = 100/repSelected.Count(); 
     int i = 0; 
     //Iterate through list and run rar for each 
     foreach (string rep in repSelected) 
     { 
      // Report progress if somebody is listening (subscribed) 
      if (ReportProgress != null) 
      { 
       ReportProgress(this, new ProgressArgs { Percentage = i, Message = "Raring files for " + rep }); 
      } 

      DirectoryExists(rep); 
      ProcessRunner(rep); 
      i += step; 

      // Report progress if somebody is listening (subscribed) 
      if (ReportProgress != null) 
      { 
       ReportProgress(this, new ProgressArgs { Percentage = i, Message = "Raring files for " + rep }); 
      } 
     } 
    } 
} 
+0

Esattamente quello che cercavo, +1! –

+0

Naturalmente questo potrebbe essere ottimizzato un po 'ed esteso, ma si ottiene l'idea di base. =) –

5

L'oggetto sender nella chiamata DoWork è l'istanza BackgroundWorker che sta chiamando questa richiamata.

Ciò consente di utilizzare l'istanza e aggiungerla alla nuova classe XMLandRar.

private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e) 
{ 
    var worker = sender as BackgroundWorker. 
    xXMLandRar.RarFiles(repSelected, worker); 
} 

XMLandRar.cs

public class XMLandRar 
{ 
    public void RarFiles(List repSelected, BackgroundWorker worker) 
    { 
    // ... 
    } 
} 


O si imposta l'istanza BackgroundWorker come una proprietà di classe al XMLandRar.

public class XMLandRar 
{ 
    protected BackgroundWorker mWorker; 

    public XMLandRar(BackgroundWorker worker) { 
     mWorker = BackgroundWorker; 
    } 


    public void RarFiles(List repSelected) 
    { 
     // Do something with {mWorker} 
    } 
} 

O come accennato nei commenti, utilizzando gli eventi nella classe XMLandRar.

XMLandRar.cs

public class XmlandRarCompletedEventArgs : EventArgs 
{ 
    public readonly bool Finished; 
    public readonly bool Canceled; 

    public XmlandRarCompletedEventArgs(bool finished) 
    { 
     Finished = finished; 
     Canceled = !finished; 
    }  

}public class OnXmlandRarUpdateEventArgs : EventArgs 
{ 
    public readonly int Percentage; 
    public readonly string Message; 

    public XmlandRarCompletedEventArgs(int perc) : 
     this(perc, "") { 
    } 

    public XmlandRarCompletedEventArgs(int perc, string message) 
    { 
     Percentage = perc; 
     Message = message; 
    }  

} 

public delegate void OnXmlandRarDoWorkHandler(object o); 
public delegate void OnXmlandRarUpdateHandler(object o, OnXmlandRarUpdateEventArgs args); 
public delegate void OnXmlandRarCompleteHandler(object o, XmlandRarCompletedEventArgs args); 

public class XMLandRar 
{ 
    public event OnXmlandRarDoWorkHandler OnDoWork; 
    public event OnXmlandRarUpdateHandler OnUpdate; 
    public event OnXmlandRarCompletedHandler OnComplete; 

    public void RarFiles(List repSelected) 
    { 
     TriggerDoWork(); 

     int step = 100/repSelected.Count(); 
     int i = 0; 
     //Iterate through list and run rar for each 
     foreach (string rep in repSelected) 
     { 
      TriggerUpdate(i, "Raring files for " + rep); 
      DirectoryExists(rep); 
      ProcessRunner(rep); 
      i += step; 
      TriggerUpdate(i, "Raring files for " + rep); 
     } 

     TriggerComplete(true); 
    } 


    private void TriggerDoWork() 
    { 
     if (OnDoWork != null) { 
      OnDoWork(this); 
     } 
    } 

    private void TriggerUpdate(perc) { 
    } 
     if (OnUpdate != null) { 
      OnUpdate(this, new OnXmlandRarUpdateEventArgs(perc)); 
     } 

    private void TriggerUpdate(perc, string message) 
    { 
     if (OnUpdate != null) { 
      OnUpdate(this, new OnXmlandRarUpdateEventArgs(perc, message)); 
     } 
    } 

    private void TriggerComplete(bool finished) 
    { 
     if (OnComplete != null) { 
      OnComplete(this, new XmlandRarCompletedEventArgs(finished)); 
     } 
    } 
} 

Usage:

private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e) 
{ 
    var worker = sender as BackgroundWorker; 
    // Attach events to class 
    xXMLandRar.OnDoWork += delegate(object o) { 
     // ... 
    }; 
    xXMLandRar.OnUpdate += delegate(object o, OnXmlandRarUpdateEventArgs args) { 
     // ... 
    }; 
    xXMLandRar.OnComplete += delegate(object o, XmlandRarCompletedEventArgs args) { 
     // ... 
    }; 
    xXMLandRar.RarFiles(repSelected, worker); 
} 

Speriamo senza causa errori di battitura' io sono in ufficio.

+0

@HenkHolterman - Si può elaborare in un rispondi per favore? Vuoi dire che per essere una corretta classe riusabile, i RarFiles non devono conoscere la GUI in quanto ciò renderebbe specifico questa situazione? –

+0

@HenkHolterman Quindi quello che devo veramente fare è separare il codice di modifica della GUI, inserirli nel modulo principale e avere solo un evento generico di aggiornamento del rapporto/callback nella classe che qualsiasi forma/CLI/pagina può ascoltare ed elaborare in è il proprio modo? –

+0

Ho aggiornato la mia risposta, se questo aiuta .. –

0

Ho fissato errori nel codice presentato e puliti it up ... Questo è un esempio funzionante che aiuterà quelli che forse non potrebbero capire il codice da quando è stato rotto come era ... Anche se vorrei dire che l'intento e la funzionalità del codice dopo che è stato pulito up and enhanced è eccellente.

Questo è un codice funzionante che consente di iniziare a utilizzare il thread backGroundWorker per qualsiasi esigenza.

Basta modificare questo metodo -

public void RarFiles(List<string> repSelected) 

per fare tutto ciò il lavoro è necessario. Sarà inoltre necessario modificare gli argomenti si prevede di utilizzare .. IE potrebbe essere necessario un DataTable o un oggetto personalizzato ... È possibile modificare il

 public class OnXmlandRarUpdateEventArgs : EventArgs 

Per le vostre esigenze .. in questo modo quando si ottiene un richiamata .. È possibile aggiornare il modulo principale dell'interfaccia utente con le modifiche apportate a tali elementi ..

potrebbe essere necessario fare qualche ritocco .. ma si vede che cosa voglio dire ..

Questo è il codice modulo. Non dimenticare di creare un pulsante sul modulo ...

using System; 
    using System.Collections.Generic; 
    using System.ComponentModel; 
    using System.Data; 
    using System.Drawing; 
    using System.Linq; 
    using System.Text; 
    using System.Windows.Forms; 

    namespace ThreadSample 
    { 
     public partial class Form1 : Form 
     { 
      List<string> repSelected = new List<string>(); 
      XMLandRar xXMLandRar = new XMLandRar(); 
      BackgroundWorker CreateRarBW = new BackgroundWorker(); 
      public Form1() 
      { 
       InitializeComponent(); 
       repSelected = new List<string> { "asdf", "asdfsd", "h;ljj" }; 
       CreateRarBW.DoWork += new DoWorkEventHandler(CreateRarBW_DoWork); 
      } 

      private void Rarbtn_Click(object sender, EventArgs e) 
      { 
       //GetReps(); 

       //Run worker 
       if (!CreateRarBW.IsBusy) 
       { 
        // This should be done once, maybe in the contructor. Bind to new event. 
        xXMLandRar.ReportProgress += new EventHandler<XMLandRar.ProgressArgs>(xXMLandRar_ReportProgress); 

        CreateRarBW.RunWorkerAsync(); 
       } 
      } 

      protected void xXMLandRar_ReportProgress(object sender, XMLandRar.ProgressArgs e) 
      { 
       // Call the UI backgroundworker 
       CreateRarBW.ReportProgress(e.Percentage, e.Message); 
      } 

      //private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e) 
      //{ 
      // var worker = sender as BackgroundWorker; 
      // xXMLandRar.RarFiles(repSelected, worker); 
      //} 


      private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e) 
      { 
       var worker = sender as BackgroundWorker; 
       // Attach events to class 
       xXMLandRar.OnDoWork += delegate(object o) 
       { 
        // ... 
        MessageBox.Show("Hey ... Something is going on over there in the classLib .. " + o); 
       }; 
       xXMLandRar.OnUpdate += delegate(object o, OnXmlandRarUpdateEventArgs args) 
       { 
        // ... 
        //foreach (object oo in args) 
        { 
         MessageBox.Show("Hey ... Something is going on over there in the classLib .. Message is " + args.Message + " and Percentage is " + args.Percentage); 
        } 
       }; 
       xXMLandRar.OnComplete += delegate(object o, XmlandRarCompletedEventArgs args) 
       { 
        MessageBox.Show("Hey ... Something is going on over there in the classLib .. Canceled is " + args.Canceled + " and Finished is " + args.Finished); 
        // ... 
       }; 
       xXMLandRar.RarFiles(repSelected);//, worker); 
      } 
     } 
    } 

Questo è il codice classe. Si può solo creare una classe nel progetto corrente ... Tenete a mente che l'oggetto è un'istanza CreateRarBW BackgroundWorker ... (non è stata inclusa sopra ..)

using System; 
    using System.Collections.Generic; 
    using System.Data; 
    using System.Drawing; 
    using System.Linq; 
    using System.Text; 
    using System.IO; 
    using System.Diagnostics; 
    using System.Threading; 

    namespace ThreadSample 
    { 
     public class XmlandRarCompletedEventArgs : EventArgs 
     { 
      public readonly bool Finished; 
      public readonly bool Canceled; 

      public XmlandRarCompletedEventArgs(bool finished) 
      { 
       Finished = finished; 
       Canceled = !finished; 
      } 
     } 

     public class OnXmlandRarUpdateEventArgs : EventArgs 
     { 
      public readonly int Percentage; 
      public readonly string Message; 


      public OnXmlandRarUpdateEventArgs(int perc) : this(perc, "") 
      { 

      } 

      public OnXmlandRarUpdateEventArgs(int perc, string message) 
      { 
       Percentage = perc; 
       Message = message; 
      } 

     } 

     public delegate void OnXmlandRarDoWorkHandler(object o); 
     public delegate void OnXmlandRarUpdateHandler(object o, OnXmlandRarUpdateEventArgs args); 
     public delegate void OnXmlandRarCompleteHandler(object o, XmlandRarCompletedEventArgs args); 

     public class XMLandRar  // : BackgroundWorker 
     { 

      // Event handler to bind to for reporting progress 
      public EventHandler<ProgressArgs> ReportProgress; 

      // Eventargs to contain information to send to the subscriber 
      public class ProgressArgs : EventArgs 
      { 
       public int Percentage { get; set; } 
       public string Message { get; set; } 
      } 

      public event OnXmlandRarDoWorkHandler OnDoWork; 
      public event OnXmlandRarUpdateHandler OnUpdate; 
      public event OnXmlandRarCompleteHandler OnComplete; 

      public void RarFiles(List<string> repSelected) 
      { 
       TriggerDoWork(); 

       int step = 100/repSelected.Count(); 
       int i = 0; 
       //Iterate through list and run rar for each 
       foreach (string rep in repSelected) 
       { 
        TriggerUpdate(i, "Raring files for " + rep); 
        //DirectoryExists(rep); 
        //ProcessRunner(rep); 
        i += step; 
        TriggerUpdate(i, "Raring files for " + rep); 
       } 

       TriggerComplete(true); 
      } 


      private void TriggerDoWork() 
      { 
       if (OnDoWork != null) 
       { 
        OnDoWork(this); 
       } 
      } 

      private void TriggerUpdate(int perc) 
      { 

       if (OnUpdate != null) 
       { 
        OnUpdate(this, new OnXmlandRarUpdateEventArgs(perc)); 
       } 
      } 

      private void TriggerUpdate(int perc, string message) 
      { 
       if (OnUpdate != null) 
       { 
        OnUpdate(this, new OnXmlandRarUpdateEventArgs(perc, message)); 
       } 
      } 

      private void TriggerComplete(bool finished) 
      { 
       if (OnComplete != null) 
       { 
        OnComplete(this, new XmlandRarCompletedEventArgs(finished)); 
       } 
      } 
     } 

    } 
Problemi correlati