Colabora |
Programación Multi-Hebra[Los Threads]
Fecha: 10/Sep/2007 (10-09-07)
|
Introducción
Contenidos que se explicaránBueno antes de nada, empezaremos por la descripción de algunas funciones que usaremos del espacio de nombres ( System.Threading ) New:Como os podeis imaginar, este es el constructor de la clase, el cual nos pide como único parametro el procedimiento que queremos que ejecute en esta Hebra ( Hilo ). Nota: El procedimiento o función a llamar a tràves de una hebra no puede contener parametros. Abort:Bueno....pongamonos en el caso de que estamos estudiando para un examen muy importante ( HebraA ), y de golpe y porrazo nos entra hambre, pero no podemos dejar de estudiar!!! Start:Lo usaremos para inicializar la Hebra ( Hilo ) Sleep:No se si os acordais de las API's de VB6...pero havia una declaración que si mal no recuerdo era: Join:Bueno hagamos honor otra vez a otro ejemplito de los mios jejej... (Gràcias a una persona del foro que me explicó bien que era Join() porque hay carencia de información sobre este tema ) ThreadPool.QueueUserWorkItem ( Cola De Espera )Tambien haremos hincapié en la cola de espera que nos ofrece este espacio de nombres...con esto quiero decir, que con un solo Click en algun boton o con algun otro metodo podemos mandar una lista de procesos y que los vaya el solíto haciendo uno detràs de otro sin que nosotros tengamos que inicializar uno por uno... Nota: QueueUserWorkItem nos pide dos parametros. Uno es el procedimiento que se pone a la cola, y otro que es el WaitHandle, que como es una clase abstracta, podemos usar un AutoResetEvent. Nota: Ejemplo 1 ( Simple llamada de un hilo):A continuación haremos un ejemplo sencillito, que consistira en abrir una nueva hebra ( Hilo o como querais llamarlo ) para realizar una tarea que consistira en escribir el la "Ventana Inmediata" Hagamos una tabla de ejemplo para ver que pasaria en nuestra CPU si le picamos 3 veces al boton.
Como podemos observar en la tabla, hay tres procesos abiertos pero se van turnando para ejecutarse. Simplemente esto es lo que deduciremos viendo los resultados que se escribirán en la "Ventana Inmediata". El primero ejemplo constara tan solo de un boton y un procedimiento que lo llamaremos Resultado. Pues bien sin mas preambulos empezemos con el codigo... Imports System.Threading Public Class Form1 Private Sub Resultado() For I As Integer = 1 To 50 Step 1 Debug.Print(I & " De 50") 'Escribimos el mensaje en la pantalla inmediata Thread.Sleep(100) 'Entre mensaje y mensaje damos un retardo de 100 Millisegundos Next End Sub Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim SubProceso As New Thread(AddressOf Resultado) SubProceso.Start() End Sub End Class Sencillo verdad? Entonces sigamos con los siguientes ejemplos Ejemplo AbortBueno en este ejemplito veremos como Abortar un proceso por si este se nos hace muy largo... En nuestro caso haremos un bucle infinito, del cual solo se podra terminar Abortando la hebra que lo lleva a cabo. Para realizar este ejemplo necesitaremos tan solo dos botones y el procedimiento Resultado(), el cual lo modificaremos para que en vez de un bucle For/Next tenga un Do/Loop. Imports System.Threading Public Class Form1 'Cambiamos el ambito de la variable para que podamos acceder ' desde cualquier parte de la Clase Form1 Dim SubProceso As Thread Private Sub Resultado() Dim I As Integer Do I += 1 Debug.Print(I & " De 50") 'Escribimos el mensaje en la pantalla inmediata Thread.Sleep(100) 'Entre mensaje y mensaje damos un retardo de 100 Millisegundos Loop End Sub Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click SubProceso = New Thread(AddressOf Resultado) SubProceso.Start() 'Iniciamos la nueva hebra ( Hilo ) con el procedimiento Resultado() End Sub Private Sub Button2_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click SubProceso.Abort() 'Abortamos el proceso y asi conseguiremos cerrar el bucle infinito. End Sub d End Class Ejemplo Join() y Thread.QueueUserWorkItem()En este ejemplo explicare la manera de hacer colas de espera para realizar procesos en cadena, por ejemplo, tenemos dos procesos uno que abre un archivo y el otro que copia el texto del archivo en el porta-papeles ( Clip Board ). Logicamente no podemos guardar el texto en el porta-papeles si previamente no hemos obtenido el texto del archivo..primero tendriamos que abrirlo y todo eso antes nada no creeis? pues para esto nos puede servir las colas de espera, pues no realizara el siguiente procedimiento o funcion hasta que no acabe el que esta antes. Imports System.Threading Public Class Form1 'Cambiamos el ambito de la variable para que podamos acceder ' desde cualquier parte de la Clase Form1() Dim SubProceso As Thread Private Sub Proceso1() For I As Integer = 1 To 50 Step 1 'Escribimos el mensaje en la pantalla inmediata Debug.Print(I & " De 50") 'Entre mensaje y mensaje damos un retardo de 100 Millisegundos Thread.Sleep(100) Next I 'Escribimos el mensaje de finalización en la pantalla inmediata. Debug.Print("Proceso1 Finalizado") End Sub Private Sub Proceso2(ByVal InfoStatus As Object) For I As Integer = 1 To 50 Step 1 'Escribimos el mensaje en la pantalla inmediata Debug.Print(I & " De 50") 'Entre mensaje y mensaje damos un retardo de 100 Millisegundos Thread.Sleep(100) Next I 'Escribimos el mensaje de finalización en la pantalla inmediata. Debug.Print("Proceso2 Finalizado") 'Cambiamos el valor de InfoStatus a TRUE para indicar que ' ya hemos finalizado el proceso y saltar al siguiente CType(InfoStatus, AutoResetEvent).Set() 'Tambien podriamos usar esto que viene a ser lo mismo que Ctype(Etc...); 'DirectCast(InfoStatus, AutoResetEvent).Set() End Sub Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click SubProceso = New Thread(AddressOf Proceso1) 'Declaramos el famoso WaitHandle que comenté anteriormente ' para detectar cuando el proceso a finalizado. Dim Evento As New AutoResetEvent(False) 'Iniciamos la nueva hebra ( Hilo ) con el procedimiento Proceso1() SubProceso.Start() 'No dejamos que se inicie otro proceso hasta que el Proceso1 no finalize SubProceso.Join() 'Ponemos el Proceso2 en cola de espera ThreadPool.QueueUserWorkItem(AddressOf Proceso2, Evento) 'No dejamos que se inicie otro proceso hasta que el Proceso2 no finalize Evento.WaitOne() 'Iniciamos el Proceso2 como ejemplo de que pondemos incluso repetirlos... ThreadPool.QueueUserWorkItem(AddressOf Proceso2, Evento) 'Etc.... End Sub End Class Diferencias Entre VB.Net2003 y VB.Net 2005Si lo que queremos esque, en vez de escribirlo en la Ventana Inmediata, se escriba todo esto en un ListBox, en la versión de Visual BASIC .Net 2005 nos dara un error en cuyo antecesor no se quejava. Conclusiones FinalesEspero que este pequeño articulo os sirva de ayuda para realizar Sub Tareas sin que este afecte a el buen funcionamiento de nuestra aplicación. Agradecimientos Por La Ayuda.Agradezco la ayuda a aibo_alcoi que me hizo una aclaración sobre la función Join(), y a todos los que ayudais desinteresadamente en los foros del guille. Espacios de nombres usados en el código de este artículo:System.Threading |
Código de ejemplo (comprimido): |
Fichero con el código de ejemplo: Threads.zip - (138) KB
|