Prácticamente todos los entornos de desarrollo permiten el uso de "threads" en sus aplicaciones y efectivamente este es el caso de .NET. Desgraciadamente cada tecnología tiene una ideología distinta para acceder a los hilos, por ejemplo en Java para usar "threads" se debe crear una clase que implemente la interfaz Thread, o en C bajo Unix se puede usar el clásico "fork".
En .NET cuando lanzamos un hilo, le asociamos una función, de manera que una vez se arranca el hilo, ejecutará esta función. En cierto modo nos simplifica la forma de programar, pues solo tendremos que programar la función y después simplemente crearemos un hilo para ejecutarla.
El ejemplo que voy a utilizar es muy sencillo, un "thread" principal se encarga de lanzar varios hilos, cuyo número limitaremos, que mostrarán por consola un año de un array, sin que dos hilos cojan el mismo elemento del array.
El número de hilos abiertos los controlaremos con un semáforo. Para poder manejar este semáforo, nos apoyaremos en la clase Interlocked, en concreto los métodos Interlocked.Increment([semaforo]) y Interlocked.Decrement([semaforo]). Estos métodos nos permiten incrementar o reducir en uno el valor del semáforo de manera "thread-safe", es decir, que todos los hilos actualizan a la vez el valor del semáforo. El semáforo será un atributo "shared" de la clase, lo cual permite que los hilos lo compartan.
Os muestro el código a continuación:
'Semaforo Private Shared opened As Integer Private years As Integer() = {1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011} Private Sub threadLauncher(threadLimit As Int16) opened = 0 Dim i As Integer = 0 'Mientras haya algún thread abierto, o queden años por procesar While (Interlocked.Read(opened) > 0 Or i < years.Count) 'Si el número de hilos abiertos es menor que el máximo, y quedan 'años por procesar, creamos un nuevo hilo If (Interlocked.Read(opened) < threadLimit And i < years.Count) Then Dim workerThread As New Thread(AddressOf processYear) workerThread.Start(i) i += 1 'Indicamos a todos los hilos abiertos, que hemos reservado uno nuevo Interlocked.Increment(opened) End If Thread.Sleep(10) End While End Sub Private Sub processYear(index As Object) Dim i As Integer = DirectCast(index, Integer) Dim str As String = String.Format("Procesando año {0}", years(i)) 'Esperamos un tiempo aleatorio en cada hilo, para que no se muestren en orden Thread.Sleep(New Random().Next(100)) System.Console.WriteLine(str) 'Indicamos al hilo principal, que se acaba de liberar un hilo. Interlocked.Decrement(opened) End Sub
Al ejecutar el método threadLauncher con un límite de 5, he obtenido los siguientes resultados:
Procesando año 1989 Procesando año 1988 Procesando año 1984 Procesando año 1986 Procesando año 1990 Procesando año 1987 Procesando año 1993 Procesando año 1992 ......
Como era de esperar, los hilos acaban en distintos momentos y por lo tanto no siguen un orden establecido, pero no obstante lo que no ocurre es que dos hilos compitan por el mismo recurso, en este caso, que dos hilos procesen el mismo año.
Y con esto acabamos el artículo sobre hilos en .NET, espero que os haya servido como ilustración para saber por donde empezar a lidiar con los hilos.
No hay comentarios:
Publicar un comentario