none
No se ejecuta el timer pork ?? RRS feed

  • Pregunta

  • Hoal en el evento onclick de un boton llamo a una funcion k se llama Proceso_Inicio que a su vez enal final llama otra funcion que en dependencia de los elemntos comparativos ejecuta un timer correspondiente k llama de nuevo a la funcion Proceso_Inicio lo k ocurre es k no se ejecutan los timer cuando debugueo no cae en el breakpoint ese y no c pork aski le spongo las funciones

     private void btn1_Play_Click(object sender, EventArgs e)
            {
                TcpClient c = new TcpClient();
                string name = lbl_nameEstufa.Text;
                c = Devolver_Cliente(name);
                if (c!=null)
                {

                    Thread Inicio = new Thread(new ThreadStart(() => Proceso_Inicio(c,0)));
                    Inicio.Start();
                    
                }
                else
                {
                    MessageBox.Show("No esta conectado la Estufa selecionada");
                }
                
            }

    private void Proceso_Inicio(TcpClient client,int cont)

    {

       /****** Hago unas cuantas cosas*****/

      Ejecutar_Timer_Inicio(nombre);

    }

    private void Ejecutar_Timer_Inicio(string nombre)
            {
                if (nombre == "Estufa 1")
                {
                    timerIni1.Start();
                }
                else if (nombre == "Estufa 2")
                {
                    timerIni2.Start();
                }
                else if (nombre == "Estufa 3")
                {
                    timerIni3.Start();
                }
                else if (nombre == "Estufa 4")
                {
                    timerIni4.Start();
                }
                else if (nombre == "Estufa 5")
                {
                    timerIni5.Start();
                }
            }

     private void timerIni1_Tick(object sender, EventArgs e)//A esta parte nunca llega el debugueo y no me da error ni nada
            {
                Proceso_Inicio(cliente1,0);
            }

    martes, 12 de junio de 2018 18:42

Respuestas

  • Donde dices "timer", ¿qué Timer es? ¿Es un System.Windows.Forms.Timer? Si es así, no lo puedes usar desde un Thread. Ese Timer depende de la bomba de mensajes de Windows, por lo que queda vinculado al Thread principal de la UI, y se bloquea si dicho thread está ocupado.

    Te sugiero usar un System.Timers.Timer o System.Threading.Timer, que a diferencia del System.Windows.Forms.Timer no dependen del hilo principal.

    • Marcado como respuesta jlpavon1987 miércoles, 13 de junio de 2018 11:32
    martes, 12 de junio de 2018 21:05
    Moderador
  • Si amigo pero el problema es que en mi caso misubrutina tienes un parametro nombre

    No, "miSubrutina" NO tiene un parametro nombre. Esa es la subrutina que se ejecuta cada vez que se dispara el Timer. El Timer vine programado en las librerías del sistema, no conoce ningun dato de tu programa, tal como el Nombre. Luego el Timer tiene que llamar a alguna subrutina sin pasarle ningún parámetro. Y después, esa subrutina, si es necesario, puede recuperar el nombre de donde lo tengas almacenado y pasárselo a la subrutina "auténtica" que usa el nombre.

    ¿Y no hay una alternativa? Sí, hay dos:

    La primera es pasarle el Nombre al Timer y luego dejar que el Timer tome ese dato. Eso se hace mediante ese parámetro que dijimos que "no necesitas usar". Puedes usarlo para contener el nombre:

    System.Threading.Timer timerini1 = new System.Threading.Timer(time, Nombre, 0, 60000);

    ...

    public void miSubrutina(object stateInfo) { string nombre = stateInfo as string; ...}

    La otra forma es usando un "Closure" mediante un delegado anónimo o una lambda. Pero si ya te perdías con el código anterior, entonces ni se me ocurre sugerirte que uses este mecanismo.

    Editado: Lo acabo de probar en una aplicación de consola y funciona bien con el código siguiente (obviamente donde pone "Hola" pondrías el parámetro que quieras pasarle):

            private static void ProbarTimer()
            {
                System.Threading.Timer miTimer = new System.Threading.Timer(MiCallback, "Hola", 250, 2000);
            }
    
            private static void MiCallback(object estado)
            {
                Console.WriteLine("Estamos en el Timer: " + estado.ToString());
            }

    miércoles, 13 de junio de 2018 18:27
    Moderador

Todas las respuestas

  • hola

    veo que usas un thread, mmm no creo que puedas acceder a las instancias de estos timer de forma global

    deberias crear una instancia de un timer dentro de Ejecutar_Timer_Inicio ademas podrias evaluar usar

    Thread Timers (C#)

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    martes, 12 de junio de 2018 20:42
  • Donde dices "timer", ¿qué Timer es? ¿Es un System.Windows.Forms.Timer? Si es así, no lo puedes usar desde un Thread. Ese Timer depende de la bomba de mensajes de Windows, por lo que queda vinculado al Thread principal de la UI, y se bloquea si dicho thread está ocupado.

    Te sugiero usar un System.Timers.Timer o System.Threading.Timer, que a diferencia del System.Windows.Forms.Timer no dependen del hilo principal.

    • Marcado como respuesta jlpavon1987 miércoles, 13 de junio de 2018 11:32
    martes, 12 de junio de 2018 21:05
    Moderador
  • Donde dices "timer", ¿qué Timer es? ¿Es un System.Windows.Forms.Timer? Si es así, no lo puedes usar desde un Thread. Ese Timer depende de la bomba de mensajes de Windows, por lo que queda vinculado al Thread principal de la UI, y se bloquea si dicho thread está ocupado.

    Te sugiero usar un System.Timers.Timer o System.Threading.Timer, que a diferencia del System.Windows.Forms.Timer no dependen del hilo principal.

    Me podrias decir como es la sintaxis para ejecutar el System.Windows.Forms.Timer en un System.Threading.Timer k ejecute ejecute la funcion Proceso_Inicio(cliente1,0); cada 5 minutos ?? no me kedo claro como es la sintaxis..

     System.Threading.Timer timerIni1 = new System.Threading.Timer(...????????);

    no entiendo la sintaxis para llamar a la funcion, y especificarle el tiempo que kiero k se repita la llamada ??

    • Editado jlpavon1987 miércoles, 13 de junio de 2018 12:29
    miércoles, 13 de junio de 2018 12:14
  • [...] como es la sintaxis [...]

     System.Threading.Timer timerIni1 = new System.Threading.Timer(...????????);

    Yo no me la sé de memoria, pero cuando me surge una duda de este tipo lo que hago es copiar con el raton la función deseada, en este caso "System.Threading.Timer" y pegarla en un buscador tal como Bing o Google. Normalmente la primera respuesta, o una de las primeras, tiene un ejemplo. También puedes escribirlo en Visual Studio, poner el cursor encima de la palabra "Timer" en "System.Threading.Timer", y pulsar la F1 (Ayuda). Esto te lleva a la documentación de Microsoft:

    https://msdn.microsoft.com/en-us/library/system.threading.timer(v=vs.110).aspx

    Ahí tienes todas las explicaciones detalladas, y si bajas hasta el final de la página tienes un ejemplo completo que puedes incluso copiar y pegar para probarlo (en ua aplicación de consola) y luego trasladar a tu programa las partes que te vengan bien.

    Dice el refrán: "Si le das un pez lo alimentas un día. Si le enseñas a pescar, lo alimentas toda la vida".

    miércoles, 13 de junio de 2018 14:20
    Moderador
  • creeme amigo k si pido ayuda por aki es pork no doy con la solucion pero gracias
    miércoles, 13 de junio de 2018 14:44
  • A ver, veamos, el Timer se construye asi:

    var miTimer = new Timer(miSubrutina, null, 1000, 250);

    Eso hace que primero se esperen 1000 milisegundos, y despues se dispare cada 250 milisegundos. Cada vez que se dispara, se ejecuta "miSubrutina", que tiene que tener este aspecto:

    public void miSubrutina(object stateInfo) {...}

    No tienes que hacer nada con el stateInfo, pero es obligatorio declararlo aunque no lo uses.


    miércoles, 13 de junio de 2018 16:31
    Moderador
  • Si amigo pero el problema es que en mi caso misubrutina tienes un parametro nombre

    entonces cuando la creo por ejemplo misubrutina(object stateInfo, string nombre)

    me da error de sintaxis cuando hago esto ya k me dice k no toma 1 argumento y cuando le paso los dos parametros es decir el de tipo object y el string me da Method name expected...

    System.Threading.TimerCallback time = new TimerCallback(Inicio_Timer_Estufa(name));
    System.Threading.Timer timerini1 = new System.Threading.Timer(time, null, 0, 60000);

    name es un string k se lo paso por parametro al metodo k implementa esto, e Inicio_Timer_Estufa es miSubrutina


    mira los metodos para que entiendas mejor

    private void Ejecutar_Timer_Inicio(string nombre)
            {
                string name = nombre;            
                System.Threading.TimerCallback time = new TimerCallback(Inicio_Timer_Estufa(name));
                System.Threading.Timer timerini1 = new System.Threading.Timer(time, null, 0, 60000);
            }

    private void Inicio_Timer_Estufa(object stateinfo,string nombre)
            {
                if (nombre == "Estufa 1")
                {
                    Proceso_Inicio(cliente1, 0);
                }
                else if (nombre == "Estufa 2")
                {
                    Proceso_Inicio(cliente2, 0);
                }
                else if (nombre == "Estufa 3")
                {
                    Proceso_Inicio(cliente3, 0);
                }
                else if (nombre == "Estufa 4")
                {
                    Proceso_Inicio(cliente4, 0);
                }
                else if (nombre == "Estufa 5")
                {
                    Proceso_Inicio(cliente5, 0);
                }
            }

    Private void Proceso_Inicio(TcpClient c1, int 0)

    {

        implementacion.....................

    }

    • Editado jlpavon1987 miércoles, 13 de junio de 2018 17:05
    miércoles, 13 de junio de 2018 16:52
  • Si amigo pero el problema es que en mi caso misubrutina tienes un parametro nombre

    No, "miSubrutina" NO tiene un parametro nombre. Esa es la subrutina que se ejecuta cada vez que se dispara el Timer. El Timer vine programado en las librerías del sistema, no conoce ningun dato de tu programa, tal como el Nombre. Luego el Timer tiene que llamar a alguna subrutina sin pasarle ningún parámetro. Y después, esa subrutina, si es necesario, puede recuperar el nombre de donde lo tengas almacenado y pasárselo a la subrutina "auténtica" que usa el nombre.

    ¿Y no hay una alternativa? Sí, hay dos:

    La primera es pasarle el Nombre al Timer y luego dejar que el Timer tome ese dato. Eso se hace mediante ese parámetro que dijimos que "no necesitas usar". Puedes usarlo para contener el nombre:

    System.Threading.Timer timerini1 = new System.Threading.Timer(time, Nombre, 0, 60000);

    ...

    public void miSubrutina(object stateInfo) { string nombre = stateInfo as string; ...}

    La otra forma es usando un "Closure" mediante un delegado anónimo o una lambda. Pero si ya te perdías con el código anterior, entonces ni se me ocurre sugerirte que uses este mecanismo.

    Editado: Lo acabo de probar en una aplicación de consola y funciona bien con el código siguiente (obviamente donde pone "Hola" pondrías el parámetro que quieras pasarle):

            private static void ProbarTimer()
            {
                System.Threading.Timer miTimer = new System.Threading.Timer(MiCallback, "Hola", 250, 2000);
            }
    
            private static void MiCallback(object estado)
            {
                Console.WriteLine("Estamos en el Timer: " + estado.ToString());
            }

    miércoles, 13 de junio de 2018 18:27
    Moderador
  • Amigo disculpa k te moleste tanto pero n acabo de dar con la verdad lo k me pasa ahora es que con los tiempo k quiero k se ejecute nada mas lo hace una sola vez es deccir quiero que se ejecute dentro de 1 minuto y cada un 1 minuto por ejemplo pero nada mas itera una sola vez despues no hace mas nada esto es lo k tengo si pudieras revisar a ver k estoy haciendo mal

    private void Proceso_Inicio(TcpClient client,int cont)

    {

     /*** AKi va todo la funcionalidad del metodo*****/

    Ejecutar_Timer_Inicio(nombre);

    }

    private void Ejecutar_Timer_Inicio(string nombre)
    {

          System.Threading.TimerCallback time1 = new TimerCallback(Inicio_Timer_Estufa1);
          System.Threading.Timer timerini1 = new System.Threading.Timer(time1, nombre,60000,60000);

    }

     private void Inicio_Timer_Estufa1(object stateinfo)
        {
                contador++;
                rtx_2.Text = "Corrio"+" "+ contador.ToString();
                string nombre = stateinfo as String;
                if (nombre=="Estufa 2")
                {               
                    Proceso_Inicio(cliente2, 0);
                }           
        }

    martes, 19 de junio de 2018 20:47
  • Lo veo muy raro. Desde Proceso_Inicio creas e inicializas el Timer, pero luego en la rutina que se dispara con el timer vuelves a llamar a Proceso_Inicio, que vuelve a crear el Timer... No creo que al Timer le siente nada bien este tratamiento, tendrías que replantear la lógica de funcionamiento.
    miércoles, 20 de junio de 2018 6:17
    Moderador
  • Si gracias ya me habia dado cuenta de eso y arregle la logica como me dijistes pero igual funcionaba un poco raro y resolví con el timer de la clase System.timer.timer y me funciono bien, parece que el timer de system.threading no me funcionó bien en un winform  gracias fuistes de mucha ayuda

    • Editado jlpavon1987 miércoles, 20 de junio de 2018 18:25
    miércoles, 20 de junio de 2018 18:24