none
Hilos y timers RRS feed

  • Pregunta

  • Hola, buenos días

    Estoy trabajando en Winforms con un chat, con cliente y servidor. Implementé en la clase servidor un thread para que esté a la espera de que alguien se conecte y también un timer para que cada ciertos segundos esté revisando si algún usuario se desconectó o se conectó, y ponga en una lista los usuarios disponibles y se los muestre al cliente. El problema que he notado es que el timer afecta al thread, ya que cuando está ejecutándose el timer y en ese momento alguien se conecta, el thread no detecta que un usuario nuevo se conectó. Como puedo hacer para que al ejecutarse el timer, el thread no deje de funcionar?


    Juan Carlos Ramos

    martes, 10 de septiembre de 2019 13:59

Respuestas

  •  El problema que he notado es que el timer afecta al thread

    Normalmente el Thread debería ejecutarse de manera completamente independiente sin verse afectado por ninguna ejecución de ninguna otra cosa... a no ser que en algún momento el Thread acceda a algún resurso compartido que se encuentre bloqueado por otro thread distinto.

    En particular, hay un caso concreto en el que ocurriría precisamente la situación que has descrito: si resulta que tu thread utiliza el método Invoke para presentar algo en la interfaz de usuario, entonces se detiene hasta que la interfaz de usuario está disponible para procesar esa petición, dado que la interfaz no admite ser ejecutada desde varios threads. Si el Timer que has mencionado es un System.Windows.Forms.Timer, entonces este Timer cada vez que se dispara se ejecuta en el mismo thread de la interfaz de usuario, y por tanto bloquea a cualquier hilo que en ese momento haga una llamada al Invoke.

    Hay varias soluciones. Una sería cambiar el System.Windows.Forms.Timer por un System.Threading.Timer. Este timer usa otro hilo en lugar del de la interfaz. Pero, claro, en ese caso cualquier operación que se haga sobre la pantalla desde el Timer tendría que realizarse por medio de Invoke. Otra sería usar una cola para presentar datos en pantalla desde el hilo. La cola sería "bombeada" mediante un tercer hilo, y no importaría si se quedase bloqueado porque las operaciones críticas realizadas por el hilo "importante" seguirían procesándose. Simplemente no se mostrarían en pantalla hasta un instante más tarde, cuando el Timer terminase de ejecutarse.

    • Marcado como respuesta Juan Rodriguez 2 martes, 10 de septiembre de 2019 17:29
    martes, 10 de septiembre de 2019 14:22
    Moderador
  • hola

    >>El timer lo que hace es que si alguien se conecta, pone su nombre en el ListView

    Para que necesitas un timer para eso? que el servidor envie un mensaje a los cliente indicando que hay un nuevo usuario

    Si el usuario se registra en el servidor deberia exponer un puerto donde recibe los mensajes, por este e servidor ademas de los textos puede enviar un mensaje con algun codigo de comando que puedas parsear con datos adicionales como ser el nombre del usuario que se conecta recientemente

    la comunicacion entre cliente y servidor es ida y vuelta, cuando ingresa un nuevo usuario el server debe comunicar este evento a todos los demas clientes

    pero remarco que no necesitas un timer para ese "tiempo real" que mencionas

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta Juan Rodriguez 2 martes, 10 de septiembre de 2019 17:29
    martes, 10 de septiembre de 2019 16:15

Todas las respuestas

  • hola

    >>ya que cuando está ejecutándose el timer y en ese momento alguien se conecta, el thread no detecta que un usuario nuevo se conectó.

    pero no deberias usar ningun timer para esto

    se supone que envies mensajes indicando la conexion o desconexion de los clientes, si alguien se conecta envia un mensaje al servidor informandolo, no necesitas timer para eso

    si se desconecta lo mismo, o si cierra la app, envias antes un mensaje por socket (o el medio que uses para comunicarte) informando de la accion para actualizar el estado de ese cliente

    pero no veo que necesites de un timer

    si quieres cada x tiempo podrias realizar un ping al cliente para ver si aun esta vivo, pero es un timer de digamos 5min o algo asi, no estas validando constantemente

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    martes, 10 de septiembre de 2019 14:04
  •  El problema que he notado es que el timer afecta al thread

    Normalmente el Thread debería ejecutarse de manera completamente independiente sin verse afectado por ninguna ejecución de ninguna otra cosa... a no ser que en algún momento el Thread acceda a algún resurso compartido que se encuentre bloqueado por otro thread distinto.

    En particular, hay un caso concreto en el que ocurriría precisamente la situación que has descrito: si resulta que tu thread utiliza el método Invoke para presentar algo en la interfaz de usuario, entonces se detiene hasta que la interfaz de usuario está disponible para procesar esa petición, dado que la interfaz no admite ser ejecutada desde varios threads. Si el Timer que has mencionado es un System.Windows.Forms.Timer, entonces este Timer cada vez que se dispara se ejecuta en el mismo thread de la interfaz de usuario, y por tanto bloquea a cualquier hilo que en ese momento haga una llamada al Invoke.

    Hay varias soluciones. Una sería cambiar el System.Windows.Forms.Timer por un System.Threading.Timer. Este timer usa otro hilo en lugar del de la interfaz. Pero, claro, en ese caso cualquier operación que se haga sobre la pantalla desde el Timer tendría que realizarse por medio de Invoke. Otra sería usar una cola para presentar datos en pantalla desde el hilo. La cola sería "bombeada" mediante un tercer hilo, y no importaría si se quedase bloqueado porque las operaciones críticas realizadas por el hilo "importante" seguirían procesándose. Simplemente no se mostrarían en pantalla hasta un instante más tarde, cuando el Timer terminase de ejecutarse.

    • Marcado como respuesta Juan Rodriguez 2 martes, 10 de septiembre de 2019 17:29
    martes, 10 de septiembre de 2019 14:22
    Moderador
  • Gracias por responder.

    Pero por ejemplo, se me ocurrió poner un timer para mostrar en tiempo real los usuarios conectados, algo así:

    El timer lo que hace es que si alguien se conecta, pone su nombre en el ListView, pero mi duda es como puedo hacer eso sin el timer?


    Juan Carlos Ramos

    martes, 10 de septiembre de 2019 14:27
  • hola

    >>El timer lo que hace es que si alguien se conecta, pone su nombre en el ListView

    Para que necesitas un timer para eso? que el servidor envie un mensaje a los cliente indicando que hay un nuevo usuario

    Si el usuario se registra en el servidor deberia exponer un puerto donde recibe los mensajes, por este e servidor ademas de los textos puede enviar un mensaje con algun codigo de comando que puedas parsear con datos adicionales como ser el nombre del usuario que se conecta recientemente

    la comunicacion entre cliente y servidor es ida y vuelta, cuando ingresa un nuevo usuario el server debe comunicar este evento a todos los demas clientes

    pero remarco que no necesitas un timer para ese "tiempo real" que mencionas

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta Juan Rodriguez 2 martes, 10 de septiembre de 2019 17:29
    martes, 10 de septiembre de 2019 16:15
  • Es cierto, me puse a analizar tu recomendación y no necesito un timer, cuando alguien se conecta se envía a los demás usuarios quien se conectó y pone el nombre del usuario en mi lista. Cuando algún usuario se desconecta, en el evento form closing del cliente mando al servidor un mensaje en el cual avisa a los demás que ya se desconectó. Muchas gracias, es la primera vez que uso thread y sockets y estaba algo confundido. Pero creo que ya me quedó más claro.

    Juan Carlos Ramos

    martes, 10 de septiembre de 2019 17:32