2012-07-16 20 views
6

Tengo una aplicación simple que se dispara de una serie de tareas de datos intensivos. No tengo mucha experiencia con WinForms y me preguntaba la mejor manera de hacerlo sin bloquear la interfaz. ¿Se puede volver a utilizar backgroundWorker, o hay otra forma de hacerlo?WinForm Multithreading. ¿Utiliza backgroundworker o no?

Gracias

+0

Utilizaría el backgroundworker. – Tomtom

+0

Si solo necesitas otro hilo, usaría un trabajador de fondo, son muy fáciles de usar y la mayoría del trabajo duro se ha realizado, proporcionándote eventos simples para las diferentes etapas de la finalización del trabajo. – ThePower

+0

¿Qué quiere decir con reutilización? –

Respuesta

6

backgroundWorker puede ser utilizado.

su beneficio: le permite actualizar una barra de progreso e interactuar con los controles de la interfaz de usuario. (WorkerReportsProgress)

También tiene un mecanismo de cancelación. (WorkerSupportsCancellation)

enter image description here

3

BackgroundWorker es un hilo que también incluye la sincronización de notificación. Por ejemplo, si desea actualizar su UI cuando finaliza el escaneo, un Thread normal no puede acceder a los objetos de la interfaz de usuario (solo el subproceso de la interfaz de usuario puede hacerlo); por lo tanto, BackgroundWorker proporciona un controlador de eventos Completado que se ejecuta en el subproceso de interfaz de usuario cuando finaliza la operación.

para más información ver: Walkthrough: Multithreading with the BackgroundWorker Component(MSDN)

y un código de ejemplo simple:

var worker = new System.ComponentModel.BackgroundWorker(); 
worker.DoWork += (sender,e) => Thread.Sleep(60000); 
worker.RunWorkerCompleted += (sender,e) => MessageBox.Show("Hello there!"); 
worker.RunWorkerAsync(); 
2

Usted puede utilizar BackgroundWorker para tales requisitos. A continuación se muestra una muestra que updates a label status based on percentage task [long running] completion. Además, hay una clase de negocio de ejemplo que establece algún valor y el valor se establece en la interfaz de usuario a través del controlador ProgressChanged. DoWork es el lugar donde escribe su lógica de tareas de larga ejecución. Copiar y pegar el siguiente código después de agregar una etiqueta y un componente de trabajador de fondo en una aplicación de Winforms & probarlo. Puede depurar en varios manejadores [RunWorkerCompleted, ProgressChanged, DoWork] y echar un vistazo al método InitWorker. Observe el cancellation feature también.

using System.ComponentModel; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form3 : Form 
    { 
     private BackgroundWorker _worker; 
     BusinessClass _biz = new BusinessClass(); 
     public Form3() 
     { 
      InitializeComponent(); 
      InitWorker(); 
     } 

     private void InitWorker() 
     { 
      if (_worker != null) 
      { 
       _worker.Dispose(); 
      } 

      _worker = new BackgroundWorker 
      { 
       WorkerReportsProgress = true, 
       WorkerSupportsCancellation = true 
      }; 
      _worker.DoWork += DoWork; 
      _worker.RunWorkerCompleted += RunWorkerCompleted; 
      _worker.ProgressChanged += ProgressChanged; 
      _worker.RunWorkerAsync(); 
     } 


     void DoWork(object sender, DoWorkEventArgs e) 
     { 
      int highestPercentageReached = 0; 
      if (_worker.CancellationPending) 
      { 
       e.Cancel = true; 
      } 
      else 
      { 
       double i = 0.0d; 
       int junk = 0; 
       for (i = 0; i <= 199990000; i++) 
       { 
        int result = _biz.MyFunction(junk); 
        junk++; 

        // Report progress as a percentage of the total task. 
        var percentComplete = (int)(i/199990000 * 100); 
        if (percentComplete > highestPercentageReached) 
        { 
         highestPercentageReached = percentComplete; 
         // note I can pass the business class result also and display the same in the LABEL 
         _worker.ReportProgress(percentComplete, result); 
         _worker.CancelAsync(); 
        } 
       } 

      } 
     } 

     void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      if (e.Cancelled) 
      { 
       // Display some message to the user that task has been 
       // cancelled 
      } 
      else if (e.Error != null) 
      { 
       // Do something with the error 
      } 
     } 

     void ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      label1.Text = string.Format("Result {0}: Percent {1}",e.UserState, e.ProgressPercentage); 
     } 
    } 

    public class BusinessClass 
    { 
     public int MyFunction(int input) 
     { 
      return input+10; 
     } 
    } 
} 
+0

Gracias por la respuesta detallada. Mi preocupación es agregar mi "lógica de tareas de larga duración" al evento DoWork.Tengo varias tareas que deben ejecutarse y no parece práctico agregarlas todas al único evento de DoWork. – Brian