2011-06-26 18 views
37

Sé que tiene 3 métodos. En mi programa tengo un método para enviar un mensaje. A menudo es tarde y el programa a veces no envía el mensaje en absoluto en respuesta a la presión de un botón. A veces es tan tarde como 5 segundos de lo que esperaría y el programa se congela. Quiero usar un BackgroundWorker para enviar el mensaje como se espera y permitir que el programa se ejecute normalmente en todo momento. Tenía el código para enviar el mensaje en un manejador de botones. Ahora, ¿dónde pongo este código equivalente? Me gustaría que todo esto se maneje presionando un botón.¿Cómo utilizar un BackgroundWorker?

¿Este es el manipulador adecuado?

backgroundWorker1.RunWorkerAsync(); 

y en:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {} 

voy a poner mi código en el controlador de botón? Y esto antes:

carga.progressBar1.Minimum = 0; 
carga.progressBar1.Maximum = 100; 

Carga es mi otra forma en que el ProgressBar es. ¿Cómo uso un BackgroundWorker en este escenario?

Respuesta

57

Puede actualizar la barra de progreso únicamente desde los controladores de eventos ProgressChanged o RunWorkerCompleted, ya que estos se sincronizan con el subproceso de la interfaz de usuario.

La idea básica es. Thread.Sleep simplemente simula algo de trabajo aquí. Reemplácelo con su llamada de ruta real.

public Form1() 
{ 
    InitializeComponent(); 

    backgroundWorker1.DoWork += backgroundWorker1_DoWork; 
    backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged; 
    backgroundWorker1.WorkerReportsProgress = true; 
} 

private void button1_Click(object sender, EventArgs e) 
{ 
    backgroundWorker1.RunWorkerAsync(); 
} 

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
{ 
    for (int i = 0; i < 100; i++) 
    { 
     Thread.Sleep(1000); 
     backgroundWorker1.ReportProgress(i); 
    } 
} 

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) 
{ 
    progressBar1.Value = e.ProgressPercentage; 
} 
+0

En su Button1_Click() ejemplo - ¿cómo puedo obtener los datos devueltos por el trabajador fondo de nuevo a la principal (IU) ¿hilo? –

+0

Extraño, tengo una excepción sobre la actualización de la interfaz de usuario (barra de progreso de WPF) de mi método ProgressChanged. Además, https://stackoverflow.com/questions/9732709/the-calling-thread-cannot-access-this-object-because-a-different-thread-owns-it/43455920 parece tener un problema similar al mío, y cita la necesidad de 'Application.Current.Dispatcher.Invoke()'. ¿Alguna idea sobre esto? –

34

Sé que esto es un poco viejo, pero en caso de que otro principiante está pasando por esto, voy a compartir algo de código que cubre un poco más de las operaciones básicas, aquí es otro ejemplo que también incluye la opción para cancelar el proceso y también informar al usuario el estado del proceso. Voy a añadir en la parte superior del código dado por Alex Aza en la solución anterior

public Form1() 
{ 
    InitializeComponent(); 

    backgroundWorker1.DoWork += backgroundWorker1_DoWork; 
    backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged; 
    backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted; //Tell the user how the process went 
    backgroundWorker1.WorkerReportsProgress = true; 
    backgroundWorker1.WorkerSupportsCancellation = true; //Allow for the process to be cancelled 
} 

//Start Process 
private void button1_Click(object sender, EventArgs e) 
{ 
    backgroundWorker1.RunWorkerAsync(); 
} 

//Cancel Process 
private void button2_Click(object sender, EventArgs e) 
{ 
    //Check if background worker is doing anything and send a cancellation if it is 
    if (backgroundWorker1.IsBusy) 
    { 
     backgroundWorker1.CancelAsync(); 
    } 

} 

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
{ 
    for (int i = 0; i < 100; i++) 
    { 
     Thread.Sleep(1000); 
     backgroundWorker1.ReportProgress(i); 

     //Check if there is a request to cancel the process 
     if (backgroundWorker1.CancellationPending) 
     { 
      e.Cancel = true; 
      backgroundWorker1.ReportProgress(0); 
      return; 
     } 
    } 
    //If the process exits the loop, ensure that progress is set to 100% 
    //Remember in the loop we set i < 100 so in theory the process will complete at 99% 
    backgroundWorker1.ReportProgress(100); 
} 

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) 
{ 
    progressBar1.Value = e.ProgressPercentage; 
} 

private void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) 
{ 
    if (e.Cancelled) 
    { 
     lblStatus.Text = "Process was cancelled"; 
    } 
    else if (e.Error != null) 
    { 
     lblStatus.Text = "There was an error running the process. The thread aborted"; 
    } 
    else 
    { 
     lblStatus.Text = "Process was completed"; 
    } 
}