2012-05-22 33 views
5

Tengo una solución de trabajo que informa el progreso del texto & en una barra de progreso y una etiqueta en el formulario principal de las aplicaciones. Ahora he movido mis métodos de trabajo a una clase para que sean accesibles en múltiples formularios, etc.BackgroundWorker informe el progreso de la clase externa?

Dentro de los métodos de trabajador hay BW.ReportProgress() declaraciones que retrasan el progreso y el texto al BackgroundWorker en el formulario principal.

para dar una mejor idea aquí es el diseño de archivo:

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(); 
} 

Entonces mi clase de nueva creación que abarca todos los métodos de los trabajadores y es empujar el progreso al formulario principal.

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); 
     } 
    } 
}

El problema que estoy teniendo es que en la clase XMLandRar la CreateRarBW no se reconoce (obviamente) - ¿cómo puedo hacer una llamada ReportProgress al BW en la pantalla principal de la aplicación?

Respuesta

9

Crea un evento en tu clase XMLandRar al que puedes suscribirte.

De esta forma, la clase XMLandRar no necesita saber ni preocuparse por la interfaz de usuario o la barra de progreso; solo le importa enviar un mensaje si alguien escucha.Y también puede haber más de un abonado (digamos si desea informar al trabajador de fondo y un registro, tal vez)

Ejemplo:

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

¡Exactamente lo que estaba buscando, +1! –

+0

Por supuesto, esto podría optimizarse un poco y ampliarse, pero se obtiene la idea básica. =) –

5

El objeto sender en la devolución de llamada DoWork es la instancia BackgroundWorker que llama a esta devolución de llamada.

Esto permite utilizar la instancia y agregarla a su nueva clase 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 configura la instancia BackgroundWorker como propiedad de clase a la XMLandRar.

public class XMLandRar 
{ 
    protected BackgroundWorker mWorker; 

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


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

O como se ha mencionado en los comentarios, el uso de eventos de la clase 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)); 
     } 
    } 
} 

Uso:

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); 
} 

suerte sin causa errores tipográficos' estoy en la oficina.

+0

@HenkHolterman - ¿Se puede elaborar en una ¿por favor, contesta? ¿Quiere decir que para ser una clase reutilizable adecuada, entonces RarFiles no debe saber sobre la GUI ya que eso la haría específica para esa situación? –

+0

@HenkHolterman Entonces, lo que realmente tengo que hacer es separar el código de modificación de la GUI, ponerlo en el formulario principal y tener solo un evento de actualización de informe genérico/devolución de llamada en la clase que cualquier formulario/CLI/página pueda escuchar y procesar en es de su propia manera? –

+0

He actualizado mi respuesta, si eso ayuda .. –

0

he fijado errores en el código presentaron y se limpian arriba ... Esta es una muestra de trabajo que ayudará a aquellos que quizás no puedan entender el código ya que se rompió como estaba ... Aunque me gustaría decir que la intención y la funcionalidad del código después de que se limpió y mejorado es excelente.

Este es un código de trabajo que puede ayudarlo a comenzar en su proyecto para utilizar un hilo backGroundWorker para lo que necesite.

basta con modificar este método -

public void RarFiles(List<string> repSelected) 

para hacer lo que necesita el trabajo. También tendrá que modificar los argumentos que desee usar .. es decir, es posible que necesite un DataTable o algún objeto personalizado ... Puede modificar el

 public class OnXmlandRarUpdateEventArgs : EventArgs 

Para sus necesidades .. de esa manera cuando se obtiene una devolución de llamada .. puede actualizar su formulario de interfaz de usuario principal con los cambios realizados en los elementos ..

es posible que tenga que hacer algunos ajustes .. pero lo que quiero decir ..

Este es el código del formulario. No se olvide de crear un botón en el formulario ...

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); 
      } 
     } 
    } 

Este es el código de clase. Usted sólo puede crear una clase en su proyecto actual ... Tenga en cuenta que el objeto es una instancia de CreateRarBW BackgroundWorker ... (no se incluyó anteriormente ..)

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)); 
       } 
      } 
     } 

    } 
Cuestiones relacionadas