Explicamos con un ejemplo cómo implementar la ejecución de un proceso o tarea en segundo plano con el lenguaje de programación Microsoft Visual Basic .Net 2010. Mostramos el código fuente source code de una aplicación de ejemplo que ejecuta un proceso en segundo plano con barra de progreso usando el componente BackgroundWorker.
- Hilo de ejecución, Threads.
- Componente BackgroundWorker en Visual Basic .Net VB.Net.
- Diseño del formulario Microsoft Visual Basic .Net VB.Net.
- Desarrollar aplicación con subproceso en segundo plano o asíncrono con Visual Basic .Net.
- Código fuente source code completo de aplicación con thread o hilo asíncrono con Visual Basic .Net VB.Net.
- La aplicación AjpdSoft Proceso segundo plano con progreso VB.Net en funcionamiento.
- Artículos relacionados.
- Créditos.
Hilo de ejecución, Threads
Un hilo de ejecución o subproceso es una característica que permite a una aplicación realizar varias tareas a la vez (concurrentemente). Los distintos hilos de ejecución comparten una serie de recursos tales como el espacio de memoria, los archivos abiertos, situación de autenticación, etc. Esta técnica permite simplificar el diseño de una aplicación que debe llevar a cabo distintas funciones simultáneamente.
Un hilo es básicamente una tarea que puede ser ejecutada en paralelo con otra tarea.
Los hilos de ejecución que comparten los mismos recursos, sumados a estos recursos, son en conjunto conocidos como un proceso. El hecho de que los hilos de ejecución de un mismo proceso compartan los recursos hace que cualquiera de estos hilos pueda modificar éstos. Cuando un hilo modifica un dato en la memoria, los otros hilos acceden a ese dato modificado inmediatamente.
Lo que es propio de cada hilo es el contador de programa, la pila de ejecución y el estado de la CPU (incluyendo el valor de los registros).
El proceso sigue en ejecución mientras al menos uno de sus hilos de ejecución siga activo. Cuando el proceso finaliza, todos sus hilos de ejecución también han terminado. Asimismo en el momento en el que todos los hilos de ejecución finalizan, el proceso no existe más y todos sus recursos son liberados.
Componente BackgroundWorker en Visual Basic .Net VB.Net
El componente BackgroundWorker permite que el formulario o control ejecute operaciones de forma asincrónica. Proporciona la posibilidad de ejecutar operaciones que llevan mucho tiempo de forma asincrónica ("en segundo plano"), en un subproceso distinto del subproceso de la IU principal de la aplicación.
La clase BackgroundWorker permite ejecutar una operación en un subproceso dedicado e independiente. Durante la ejecución de operaciones que exigen mucho tiempo, como las descargas y las transacciones de las bases de datos, puede parecer que la interfaz de usuario (UI) ha dejado de responder. Cuando se necesita una interfaz de usuario rápida, pero se producen largos retrasos asociados a tales operaciones, la clase BackgroundWorker ofrece una práctica solución.
Para ejecutar en segundo plano una operación que exija mucho tiempo, cree un objeto BackgroundWorker y realice escuchas de eventos que creen informes del progreso de la operación y que señalen su finalización. Se puede crear BackgroundWorker mediante programación o arrastrarlo al formulario desde la ficha Componentes del Cuadro de herramientas. Si crea BackgroundWorker en el Diseñador de Windows Forms, aparecerá en la Bandeja de componentes y sus propiedades se mostrarán en la ventana Propiedades.
Diseño del formulario Microsoft Visual Basic .Net VB.Net
Para el formulario de ejemplo de uso del componente BackgroundWorker (en el formulario llamado "hiloSegundoPlano") añadiremos los siguientes componentes:
- NumericUpDown: para establecer el número de iteraciones de la función de Fibonacci que será la usada en el ejemplo para realizar un cálculo que tarde un tiempo determinado y así probar el proceso en segundo plano.
- Label: mostrará el estado de la tarea ejecutada en segundo plano o background.
- ProgressBar: barra de progreso que mostrará el porcejate completado de la tarea en segundo plano.
- Button: botón para iniciar el proceso en segundo plano.
- Button: botón para cancelar el proceso en segundo plano ejecutado.
- TextBox: donde el usuario podrá escribir para comprobar que el proceso en segundo plano se está ejecutando y se puede, a su vez, interactuar con el formulario.
- Button: para limpiar el contenido del TextBox anterior.
- Button: para guardar el contenido del TextBox anterior, incluso aunque se esté ejecutando el proceso en segundo plano.
- BackgroundWorker: componente para generar el hilo o proceso en segundo plano, asíncrono o background.
- SaveFileDialog: componente para mostrar una ventana de petición de unidad, carpeta y nombre del fichero a guardar.
Estableceremos a True las propiedades WorkerReportsProgress y WorkerSupportsCancellation del componente BackgroundWorker:
Desarrollar aplicación con subproceso en segundo plano o asíncrono con Visual Basic .Net
En primer lugar crearemos un proyecto basado en Windows, desde el menú "Archivo" - "Nuevo proyecto", seleccionando "Aplicación de Windows Forms". Añadiremos los componentes que indicamos aquí al formluario principal de la aplicación.
Crearemos el procedimiento o función que será la que realice la acción que queramos ejecutar en proceso en segundo plano. Es importante mencionar que en dicho procedimiento o función no se puede hacer referencia a controles del formulario. Por ejemplo, si queremos mostrar una barra de progreso con el estado de la tarea, deberemos hacer referencia a la barra de progreso en el evento ProgressChanged del componente BackgroundWorker, si intentamos hacer una referencia a algún componente del formulario desde el procedimiento o función se producirá un error.
Añadiremos dicho procedimiento, en nuestro caso un ejemplo de cálculo de la Sucesión de Fibonacci:
Function CalcularFibonacci(ByVal n As Integer,
ByVal worker As BackgroundWorker,
ByVal e As DoWorkEventArgs) As Long
'No permitimos valores superiores a 91 ni inferiores a 9
If n < 0 OrElse n > 91 Then
Throw New ArgumentException( _
"value must be >= 0 and <= 91", "n")
End If
Dim result As Long = 0
iteraciones = iteraciones + 1
'Si el usuario ha pulsado el botón cancelar abortar la operación
If worker.CancellationPending Then
e.Cancel = True
Else
If n < 2 Then
result = 1
Else
result = CalcularFibonacci(n - 1, worker, e) + _
CalcularFibonacci(n - 2, worker, e)
End If
'Establecemos el % de progreso realizado del total de la tarea
Dim percentComplete As Integer = _
CSng(n) / CSng(numberToCompute) * 100
If percentComplete > highestPercentageReached Then
highestPercentageReached = percentComplete
worker.ReportProgress(percentComplete)
End If
End If
Return result
End FunctionEn la función anterior hemos incluido las líneas de código:
Para controlar si el usuario ha pulsado el botón cancelar, de esta forma cancelaremos el proceso en segundo plano.If worker.CancellationPending Then e.Cancel = True Else ....
También la línea:
worker.ReportProgress(percentComplete)
Para devolver el porcentaje actual del progreso.
Como se puede observar en el código de la función, nunca se hace referencia a un componente del formulario.
Por otro lado en el evento DoWork del componente BackgroundWorker, agregaremos una llamada al método CalcularFibonacci:
Private Sub hiloSegundoPlano_DoWork(ByVal sender As System.Object,
ByVal e As System.ComponentModel.DoWorkEventArgs) _
Handles hiloSegundoPlano.DoWork
'Obtener el objeto BackgroundWorker que provocó este evento
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
'Asignar el resultado de la computación a la propiedad Result
'del objeto DoWorkEventArgs
e.Result = CalcularFibonacci(e.Argument, worker, e)
End Sub
En el procedimiento anterior (DoWork) ejecutaremos la función CalcularFibonacci pasándole varios parámetros para permtir la cancelación del proceso y para mostrar la información del progreso.
Es importante que el controlador de eventos DoWork no haga referencia directamente a la variable de la instancia BackgroundWorker (en el ejemplo llamado "hiloSegundoPlano"), ya que esto uniría este controlador de eventos a una instancia específica de BackgroundWorker. En su lugar, se recupera del parámetro sender una referencia al control BackgroundWorker que provocó este evento. Esto es importante cuando el formulario aloje más de un BackgroundWorker.
Para implementar la información de progreso, declaremos tres variables en el formulario formProceso. Éstas se utilizarán para realizar el seguimiento del progreso:
Public Class formProceso
Private numeroSeriesFib As Integer = 0
Private highestPercentageReached As Integer = 0
Private iteraciones As IntegerEn el evento ProgressChanged del componente BackgroundWorker añadiremos el siguiente código:
Private Sub hiloSegundoPlano_ProgressChanged(ByVal sender As Object,
ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
Handles hiloSegundoPlano.ProgressChanged
barraProgreso.Value = e.ProgressPercentage
lInfo.Text = "Iteraciones Fibonacci: " & CStr(iteraciones)
End SubPara permitir que el usuario pueda cancelar el proceso en segundo plano, en el evento OnClick del botón btCancelarProceso introduciremos el siguiente código:
Private Sub btCancelarProceso_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles btCancelarProceso.Click
'Cancelar proceso asíncrono
hiloSegundoPlano.CancelAsync()
'Deshabilitar el botón cancelar
btCancelarProceso.Enabled = False
End SubCon estos procedimientos habremos conseguido ejecutar la función deseada (CalcularFibonacci) que puede realizar cualquier acción en segundo plano, de forma que de cara al usuario la función o procedimiento se ejecutará "sin que se entere" (si así lo deseamos). Podrá seguir interacturando con nuestra aplicación mientras se ejecuta la tarea en segundo plano. Este método es muy útil para determinados procesos donde consideremos que el usuario ni tiene que interactuar, mejorando así el rendimiento de nuestra aplicación.
Código fuente source code completo de aplicación con thread o hilo asíncrono con Visual Basic .Net VB.Net
A continuación mostramos el código fuente complento en Microsoft Visual Basic .Net de Microsoft Visual Studio 2010 como ejemplo de ejecución de tareas en segundo plano o asíncronas, con barra de progreso:
Imports System
Imports System.Threading
Imports System.Collections
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms
Imports System.IO
Public Class formProceso
Private numeroSeriesFib As Integer = 0
Private iteraciones As Integer
Private porcentajeMasAlto As Integer = 0
Function CalcularFibonacci(ByVal n As Integer,
ByVal worker As BackgroundWorker,
ByVal e As DoWorkEventArgs) As Long
'No permitimos valores superiores a 91 ni inferiores a 9
If n < 0 OrElse n > 91 Then
Throw New ArgumentException( _
"value must be >= 0 and <= 91", "n")
End If
Dim result As Long = 0
iteraciones = iteraciones + 1
'Si el usuario ha pulsado el botón cancelar abortar la operación
If worker.CancellationPending Then
e.Cancel = True
Else
If n < 2 Then
result = 1
Else
result = CalcularFibonacci(n - 1, worker, e) + _
CalcularFibonacci(n - 2, worker, e)
End If
'Establecemos el % de progreso realizado del total de la tarea
Dim porcentajeCompletado As Integer
porcentajeCompletado = CSng(n) / CSng(numeroSeriesFib) * 100
If porcentajeCompletado > porcentajeMasAlto Then
porcentajeMasAlto = porcentajeCompletado
worker.ReportProgress(porcentajeCompletado)
End If
End If
Return result
End Function
Private Sub btIniciarProceso_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles btIniciarProceso.Click
iteraciones = 0
barraProgreso.Minimum = 0
barraProgreso.Maximum = 100
lInfo.Text = [String].Empty
'Deshabilitamos el ListBox con el número de iteraciones
'hasta que concluya el proceso
txtNumeroIteraciones.Enabled = False
'Deshabilitar el botón de inicio de proceso
'hasta que el proceso asíncrono haya concluido
btIniciarProceso.Enabled = False
'Habilitamos el botón cancelar
'mientras la operación está ejecutándose
btCancelarProceso.Enabled = True
'Obtenemos el valor de iteraciones seleccionado por el usuario
numeroSeriesFib = CInt(txtNumeroIteraciones.Value)
'Iniciamos el valor de la variable que contendrá el % del progreso
porcentajeMasAlto = 0
'Iniciamos el proceso asíncrono en segundo plano
hiloSegundoPlano.RunWorkerAsync(numeroSeriesFib)
End Sub
Private Sub btLimpiar_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles btLimpiar.Click
txtTexto.Text = [String].Empty
End Sub
Private Sub btGuardar_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles btGuardar.Click
dlGuardar.Filter = "Archivos de texto (*.txt)|*.txt|Todos (*.*)|*.*"
dlGuardar.FilterIndex = 1
dlGuardar.DefaultExt = "txt"
dlGuardar.FileName = "texto"
dlGuardar.OverwritePrompt = True
dlGuardar.Title = "Guardar fichero mientras se ejecuta tarea en segundo plano"
If dlGuardar.ShowDialog Then
Try
Dim fichero As New StreamWriter(dlGuardar.FileName)
fichero.WriteLine(txtTexto.Text)
fichero.Close()
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.OkOnly + _
MsgBoxStyle.Exclamation)
End Try
End If
End Sub
Private Sub hiloSegundoPlano_DoWork(ByVal sender As System.Object,
ByVal e As System.ComponentModel.DoWorkEventArgs) _
Handles hiloSegundoPlano.DoWork
'Obtener el objeto BackgroundWorker que provocó este evento
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
'Asignar el resultado de la computación a la propiedad Result
'del objeto DoWorkEventArgs
e.Result = CalcularFibonacci(e.Argument, worker, e)
End Sub
Private Sub hiloSegundoPlano_ProgressChanged(ByVal sender As Object,
ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
Handles hiloSegundoPlano.ProgressChanged
barraProgreso.Value = e.ProgressPercentage
lInfo.Text = "Iteraciones Fibonacci: " & CStr(iteraciones)
End Sub
Private Sub hiloSegundoPlano_RunWorkerCompleted(ByVal sender As Object,
ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
Handles hiloSegundoPlano.RunWorkerCompleted
'Manejar el caso en que se produzca un error o excepción
If (e.Error IsNot Nothing) Then
MsgBox(e.Error.Message, MsgBoxStyle.OkOnly + MsgBoxStyle.Critical)
Else
If e.Cancelled Then
'Manejar el caso en que el usuario haya cancelado la operación.
lInfo.Text = "Proceso cancelado"
Else
'Manejar el caso en que la operación haya finalizado con éxito
lInfo.Text = e.Result.ToString()
End If
End If
'Habilitamos el ListBox del número de iteraciones
txtNumeroIteraciones.Enabled = True
'Habilitamos el botón de iniciar proceso
btIniciarProceso.Enabled = True
'Deshabilitamos el botón cancelar
btCancelarProceso.Enabled = False
End Sub
Private Sub btCancelarProceso_Click(
ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles btCancelarProceso.Click
'Cancelar proceso asíncrono
hiloSegundoPlano.CancelAsync()
'Deshabilitar el botón cancelar
btCancelarProceso.Enabled = False
End Sub
End Class
La aplicación AjpdSoft Proceso segundo plano con progreso VB.Net en funcionamiento
Tras seleccionar el número de iteraciones y pulsar en "Iniciar proceso asíncrono" se iniciará el proceso, mostrará la barra de progreso y se activará el botón "Cancelar proceso asíncrono". Si queremos probar que el proceso se ejecuta en segundo plano realmente y que podemos interactuar con la aplicación, podremos escribir en el cuadro de texto y guardar los cambios mientras el proceso se está ejecutando:
Si eres desarrollador de software y quieres descargar el ejemplo complento en Microsoft Visual Basic .Net 2010 regístrate en nuestra web y accede al enlace:
Artículos relacionados
- Instalar Visual Studio 2010 y desarrollar aplicación con acceso a PostgreSQL.
- El control de errores en Visual Basic .Net.
- Acceso a MySQL mediante Visual Basic .Net y ODBC.
- Acceso a Oracle mediante Microsoft Visual Basic, RDO y ODBC.
- Insertar y extraer documentos en una tabla Oracle con Visual Basic 6.
- Artículos, manuales y trucos del Proyecto AjpdSoft sobre Microsoft Visual Studio.
- Instalar el motor de bases de datos PostgreSQL en GNU Linux Debian 5.
- Instalar y administrar PostgreSQL en Microsoft Windows 7.
- Instalar el motor de base de datos PostgreSQL 8.4 en GNU Linux Ubuntu 10.
- Ejercicios resueltos en el lenguje de programación C.
- Artículos del Proyecto AjpdSoft sobre sistemas operativos (Windows, GNU Linux, etc.).
- Artículos del Proyecto AjpdSoft sobre los sistemas operativos Microsoft Windows.
- Artículos del Proyecto AjpdSoft sobre Delphi (lenguaje de programación).
- Artículos del proyecto AjpdSoft sobre Java (lenguaje de programación).
- AjpdSoft Conexión BD Visual Basic .Net.
- Todos los programas con código fuente en Visual Basic.
No hay comentarios:
Publicar un comentario