Una simple cuestión de hilos.

A cuerda de una pregunta en el foro (para principiantes),  donde se cuestiona porque el ‘timer’ deja de funcionar y no refresca el paso de los segundos cuando efectuamos una llamada a un procedimiento… vamos a exponer el siguiente argumento para intentar esclarecerlo.


Nuestro ‘Form’ se está rondando en su hilo de ejecución… por lo que cuando efectúas la llamada para “procesar la rutina”, el ‘timer’ deja de refrescarse por falta de turno de ejecución al estar (nuestro hilo) ocupado en espera de recibir el retorno de la llamada a tal procedimiento.



Para no bloquear nuestro hilo de ejecución y poder continuar con otras tareas, deberemos llamar a ese proceso creando un nuevo hilo de ejecución, utilizando ‘Threading.Thread’ … aquí dejo un ejemplo donde muestra las dos situaciones de una forma muy básica.



En situación de ejecución, nuestro ‘form’ visualiza la fecha y hora actual en la barra de titulo. Al pulsar sobre el botón 1 se lanza la llamada al procedimiento ‘readline’ en espera de leer una línea recibida por el puerto serie, todo el ‘form’ quedara congelado hasta recibir esa línea, que de buena tinta sabemos que nunca llegara J  por lo tanto la barra de titulo quedara inanimada, pues el hilo está ocupado y el ‘timer1’ no dispone de turno de ejecución para dispar los eventos ‘tick’.


Sin embargo al hacer clic sobre el segundo botón, este crea un nuevo hilo de ejecución que apunta al mismo procedimiento pero con una nueva asignacion de ejecucion, haciendo autónomo su proceso en la llamada al procedimiento, así pues en este caso la barra de titulo reflejara en todo momento la fecha y hora, con independencia de si el procedimiento a finalizado o no, pues el hilo principal del ‘form’ continuara atendiendo y repartiendo la ejecución entre todos los objetos que tiene a su cargo… inclusive el nuevo hilo.



Para rodar este ejemplo, solo tienes que crear un nuevo proyecto ‘winform’ añadir un ‘timer’ y dos ‘Button’.



Espero que os sea útil y pido ‘sorrys’ por el rollo!
Pep Lluis,


Public Class Form1
    Private Puerto As New System.IO.Ports.SerialPort

    Private Sub Form1_Load(…..) Handles MyBase.Load
        Me.Timer1.Interval = 1000
        Me.Timer1.Enabled = True
        Me.Button1.Text = “Llamar Procedimiento”
        Me.Button2.Text = “Ejecutar nuevo Hilo”
        Puerto = My.Computer.Ports.OpenSerialPort(“COM1″)
    End Sub



    Private Sub Timer1_Tick(…..) Handles Timer1.Tick
        Me.Text = Date.Now
    End Sub


    Private Sub Button1_Click(…..) Handles Button1.Click
        Me.Button1.Enabled = False
        Me.Text = “*Ejecucion sin crear Hilo “
        Procedimiento()
        Me.Button1.Enabled = True
    End Sub


    Private Sub Button2_Click(…..) Handles Button2.Click
        Me.Button2.Enabled = False
        Me.Text = “*Ejecutar creando un nuevo Hilo”
        Dim MiHilo As New Threading.Thread(AddressOf Procedimiento)
        MiHilo.Start()
        ‘el timer continua con su ejecucion…        
        ‘Antes de lanzar una nueva llamada
        ‘deberiamos cancelar el hilo en espera
        ‘ejecutando : MiHilo.Abort() o controlando
        ‘su estado o control por ejemplo con :
        MiHilo.IsAlive
        MiHilo.Suspend()
        MiHilo.Sleep()
    End Sub


    Private Sub Procedimiento()
       
        ‘Esta funcion esta efectuando una llamada
        ‘a un procedimento que no finalizara hasta
        ‘completarse o exceder su tiempo de espera.
        Dim datos = Puerto.ReadLine
    End Sub
End
Class

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>