Como dijo Marc, debe asegurarse de hacer girar un nuevo hilo para hacer su cálculo de larga ejecución. De esta manera, el hilo de la interfaz de usuario (que es el que tiene que hacer todas las actualizaciones de la pantalla) puede volver a dibujar la barra de progreso cada vez que cambie el porcentaje completado.
Es importante tener en cuenta que solo el subproceso de interfaz de usuario puede actualizar la interfaz. Entonces, una vez que está ejecutando un hilo separado, debe pasar por un aro adicional para asegurarse de que su cambio de UI se procese en el hilo de la interfaz de usuario. Si no está seguro de qué hilo se está ejecutando, puede verificar el valor de InvokeRequired (si su clase es System.Windows.Form) para ver si está realmente en el hilo de la interfaz de usuario.
Para obtener su comando procesado en el hilo de la interfaz de usuario, use la función Control.Invoke() para asegurarse de que la actualización se procesa en el subproceso de interfaz de usuario para el control con el que está trabajando.
En mi código de ejemplo a continuación, estoy creando un tipo de función de delegado y declarando la función invocada por adelantado .... No lo he hecho con ninguna de las funciones C# 3.5, pero apuesto a que podría funcionar una expresión lamba para hacer lo mismo.
private void bCreateInvoices_Click(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(CreateInvoices);
worker.RunWorkerAsync(this);
}
// Here is the long running function that needs to update the progress bar
public void CreateInvoices(object sernder, DoWorkEventArgs e)
{
int totalChecked = CountCheckedServiceOrders();
int totalCompleted = 0;
foreach (...data to process...) {
totalCompleted++;
if (InvokeRequired) {
Invoke(new Change(OnChange), "status text",
totalCompleted, totalChecked);
}
}
}
// this code updates the status while a background thread works
private delegate void Change(string status, int complete, int total);
private void OnChange(string status, int complete, int total)
{
if (status == null) {
progressBar.Visible = false;
lStatus.Text = "Task complete";
progressBar.Value = 0;
} else {
progressBar.Visible = true;
progressBar.Minimum = 0;
progressBar.Maximum = total;
progressBar.Value = complete;
lStatus.Text = status;
}
}
Tome un vistazo a la MSDN Control.InvokeRequired manual page y la MSDN Control.Invoke manual page de algo más de información.
Amigos
no sé lo suficiente sobre C# aquí para responder, pero en Java Swing it necesita tener un hilo separado o de lo contrario obtendrá este mismo comportamiento. – Chet