Ejecución de acciones en segundo plano

Normalmente cuando queremos realizar una acción y esta tarda mucho en procesarse (Consultas largas a bases de datos, obtención de archivos via ftp, etc….) la interfaz de usuario tiende a quedarse bloqueada hasta que termina dicha acción.

Para hacer que las acciones se realicen en segundo plano y que no se quede bloqueado usaremos la clase BackgroundWorker:

  • Implementar:
using System.Threading;
  • En el formulario arrastraremos el elemento “BackgroundWorker”:

  • Le seleccionamos y vamos a las propiedades:


  1. En el caso de que queramos poder parar el proceso en cualquier momento activaremos la propiedad “WorkerSupportsCancellation”.
  2. Si queremos poder ver el estado del proceso activaríamos “WorkerReportsProgress”.
  • Ahora iremos a “Eventos” y haremos click y presionaremos “ENTER” en los elementos:

  1. DoWork: Ésta función es la encargada de realizar las acciones en segundo plano.
  2. ProgressChanged: Esta es la función que se encargará de realizar las acciones referentes a la visualización del progreso, como por ejemplo actualizar una barra de progreso.
  3. RunWorkerCompleted: Aquí realizara la acción una vez terminado el proceso.
  • Veremos que en la vista de código nos habrá generado lo siguiente:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
 
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
 
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
 
}
  • En “backgroundWorker1_DoWork” introduciremos lo siguiente:
BackgroundWorker worker = sender as BackgroundWorker;
/* Aquí meteremos el proceso que queremos que realice */
  • En “backgroundWorker1_RunWorkerCompleted” en este caso introduciremos una venta de aviso que indica que el proceso se ha completado.
MessageBox.Show("El proceso a terminado.");
  • Y en “backgroundWorker1_ProgressChanged” de momento no haremos nada.
  • Ahora haremos las llamadas de los botones para que el proceso sea en segundo plano:
private void button_Click(object sender, EventArgs e)
{
   if (!backgroundWorker1.IsBusy)
       backgroundWorker1.RunWorkerAsync();
}
  • Y ahora el botón que cancelaría el proceso:
private void button2_Click(object sender, EventArgs e)
{
   backgroundWorker1.CancelAsync();
}

<html><table> <tbody><tr><th scope=“col” align=“left”><span><img id=“s-e6f6a65cf14f462597b64ac058dbe1d0-system-media-system-caps-caution” alt=“System_CAPS_caution” src=“https://i-msdn.sec.s-msft.com/dynimg/IC1429.jpeg” title=“System_CAPS_caution” xmlns=“”></span><span class=“alertTitle”>Aviso según Microsoft </span></th></tr><tr><td><p><span id=“mt6” class=“sentence” data-guid=“eef1d3a50423110ee93fc90a158febbe” data-source=“Be aware that your code in the <span class=&quot;mtpsTagOuterHtml&quot; ><span>DoWork</span></span> event handler may finish its work as a cancellation request is being made, and your polling loop may miss <span class=&quot;mtpsTagOuterHtml&quot; ><span><span class=&quot;mtpsTagOuterHtml&quot; xmlns=&quot;&quot;><span>CancellationPending</span></span></span></span> being set to <strong>true</strong>.” xml:space=“preserve”><sentencetext xmlns=“http://www.w3.org/1999/xhtml”>Tenga en cuenta que el código en el <a href=“https://msdn.microsoft.com/es-es/library/system.componentmodel.backgroundworker.dowork.aspx”>DoWork</a> controlador de eventos puede finalizar su trabajo mientras se realiza una solicitud de cancelación y el bucle de sondeo podría pasar por alto <a href=“https://msdn.microsoft.com/es-es/library/system.componentmodel.backgroundworker.cancellationpending.aspx”><span xmlns=“”>CancellationPending</span></a> se establece en <strong xmlns=“http://www.w3.org/1999/xhtml”>true</strong>.</sentencetext></span><span id=“mt7” class=“sentence” data-guid=“bb9dff7332fab64d22c7c9d95b46c950” data-source=“ In this case, the <span class=&quot;mtpsTagOuterHtml&quot; ><span><span class=&quot;mtpsTagOuterHtml&quot; xmlns=&quot;&quot;><span>Cancelled</span></span></span></span> flag of <span class=&quot;mtpsTagOuterHtml&quot; ><span>System.ComponentModel<span class=&quot;mtpsTagOuterHtml&quot; xmlns=&quot;&quot;><span>.</span></span>RunWorkerCompletedEventArgs</span></span> in your <span class=&quot;mtpsTagOuterHtml&quot; ><span>RunWorkerCompleted</span></span> event handler will not be set to <strong>true</strong>, even though a cancellation request was made.” xml:space=“preserve”><sentencetext xmlns=“http://www.w3.org/1999/xhtml”> En este caso, el <a href=“https://msdn.microsoft.com/es-es/library/system.componentmodel.asynccompletedeventargs.cancelled.aspx”><span xmlns=“”>Cancelled</span></a> marca de <a href=“https://msdn.microsoft.com/es-es/library/system.componentmodel.runworkercompletedeventargs.aspx”>System.ComponentModel<span xmlns=“”>.</span>RunWorkerCompletedEventArgs</a> en su <a href=“https://msdn.microsoft.com/es-es/library/system.componentmodel.backgroundworker.runworkercompleted.aspx”>RunWorkerCompleted</a> controlador de eventos no se establecerá en <strong xmlns=“http://www.w3.org/1999/xhtml”>true</strong>, incluso si se realizó una solicitud de cancelación.</sentencetext></span><span id=“mt8” class=“sentence” data-guid=“4ec89be77e1e148c0fefc126a2cd41a1” data-source=“ This situation is called a <em>race condition</em> and is a common concern in multithreaded programming.” xml:space=“preserve”><sentencetext xmlns=“http://www.w3.org/1999/xhtml”> Esta situación se denomina un <em xmlns=“http://www.w3.org/1999/xhtml”>condición de carrera</em> y es un problema habitual en la programación multiproceso.</sentencetext></span><span id=“mt9” class=“sentence” data-guid=“d3dc5e3e2e09df455b8335044f59cb2e” data-source=“ For more information about multithreading design issues, see <span class=&quot;mtpsTagOuterHtml&quot; ><span>Managed Threading Best Practices</span></span>.” xml:space=“preserve”><sentencetext xmlns=“http://www.w3.org/1999/xhtml”> Para obtener más información acerca del diseño de multithreading problemas, vea <a href=“https://msdn.microsoft.com/es-es/library/1c9txz50.aspx”>Managed Threading Best Practices</a>.</sentencetext></span></p></td></tr></tbody></table> </html>

Ejemplo funcionando: <html><a href=“https://www.dropbox.com/s/jzge8l5t5wx9y7h/SegundoPlano.zip?dl=0”>Ejemplo.</a></html>
En el ejemplo se ha hecho lo siguiente, se han creado 2 botones que hacen lo mismo, conseguir el código HTML de una página, en este caso he puesto terra, para que tarde en recoger los datos, una vez cargados lo muestra en un richTextBox, cuando presionamos sobre el botón “Sin Background” he intentamos mover el formulario, veremos que no nos deja. Sin en cambio sí presionamos en el que pone “Con Bakground” veremos que si se puede mover.

  • Nota: Recordar que los nombres de los controles se han de ajustar a las necesidades de cada uno.
  • Nota 2: En el ejemplo no he incluido el botón de cancelar, porque el proceso de obtención del código no permite ser detenido.

Navegación

Software de programación

Ayuda al servidor