[How To] Tareas asincrónicas en Windows Forms

enero 18, 2016 Christian Amado 0 Comentarios

Introducción

Cuando desarrollamos aplicaciones de escritorio queremos ofrecer al usuario una experiencia notable y eso implica que nuestra aplicación no se "cuelgue" cuando se realiza un proceso determinado.

Una de las peores experiencias es realizar una acción y que en la barra de título de la aplicación aparezca "No Responde". Dicha acción hace que el usuario intente hacer clic en el botón X para cerrar la aplicación automáticamente y no ver ese mensaje desagradable y el fondo de la aplicación de color blanco.

Es por eso que recurrimos a las llamadas asincrónicas dentro de un procedimiento en particular, ya que permite mostrar un mensaje al usuario de que se está procesando alguna información. Para realizar esta tarea con el .NET Framework (desde la versión 2.0) simplemente utilizaremos el componente BackgroundWorker.

Utilizando el código

Para nuestro ejemplo, utilizaremos un Formulario Windows simple en C#, con una barra de progreso y una etiqueta que mostrará el avance actual.

Creamos un proyecto nuevo, de tipo Windows Forms y lo llamaremos WinFormAsync:

En el diseño del formulario colocaremos un ProgressBar, Label y un Button:

Hacemos doble clic en el botón (con la propiedad Text "Calcular") y escribimos el código correspondiente al BackgroundWorker:
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;

namespace WinFormAsync
{
    public partial class Form1 : Form
    {
        BackgroundWorker worker = new BackgroundWorker();

        public Form1()
        {
            InitializeComponent();

            //establecemos los valores para las propiedades del Background Worker
            worker.WorkerReportsProgress = true;

            //Este evento realiza la tarea en específico
            worker.DoWork += Worker_DoWork;

            //Este evento reporta el progreso de la tarea
            worker.ProgressChanged += Worker_ProgressChanged;

            //Establecemos los valores para las propiedades del progressBarr
            pbCalculo.Visible = true;
            pbCalculo.Minimum = 0;
            pbCalculo.Maximum = 10;
            pbCalculo.Value = 0;
            pbCalculo.Step = 1;
        }

        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i <= 10; i++)
            {
                // Esperar un segundo.
                Thread.Sleep(1000);
                // Reportar progreso.
                worker.ReportProgress(i);
            }
        }

        private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pbCalculo.Value = e.ProgressPercentage;

            //Con esto mostramos el valor porcentual en la eqtiqueta
            lblPorcentaje.Text = (e.ProgressPercentage * 10).ToString() + " %";
        }

        private void btnCalcular_Click(object sender, EventArgs e)
        {
            //Verificamos que el worker no esté ocupado y ejecutamos la tarea
            if (!worker.IsBusy)
                worker.RunWorkerAsync();
        }
    }
}
Una vez cumplida la tarea veremos la barra de progreso sin que se cuelgue la aplicación: