none
Aplicación se queda congelada (Timer) RRS feed

  • Pregunta

  • Hola que tal les comento mi caso:

    Realicé una aplicación que utiliza varios Timer (para ser más exacto 3) que se apagan y se prenden cada cierto tiempo, uno de ellos esta constantemente prendido lo cargo en el load del Form principal con su propiedad enabled = true, el detalle es que después de un tiempo digamos horas esta ya no responde y se queda congelada y no responde.

    La función de esta aplicación es que recibe datos por medio del puerto serial y de un protocolo de comunicación del cual arroja ciertos datos, les pongo un trozo de código para que me orienten acerca de este problema.

    Private Sub tmrEntradas_Timer()

        Call fnRecorrerEntradas

    End Sub

    Public Function fnRecorrerEntradas()

     

        Dim c As Integer

     

        For c = 0 To 24 Step 1

     

            If c >= 24 And GBLEstatusTorreta(GBLCiclo).Torreta = 1 Then

     

                c = 0

                GBLEstatusTorreta(GBLCiclo).Torreta = GBLEstatusTorreta(GBLCiclo).Torreta + 1

                tmrEntradas.Enabled = False

                tmrEstatus.Enabled = True

                Exit Function

     

            ElseIf c >= 17 And GBLEstatusTorreta(GBLCiclo).Torreta = 2 Then

     

                c = 0

                GBLEstatusTorreta(GBLCiclo).Torreta = 1

                countProgress.Caption = ""

                tmrEstatus.Enabled = True

                tmrEntradas.Enabled = False

                Exit Function

     

            End If

     

            Call sbEntradas(c)

            Call fnDetenerTiempoDos(GBLTiempo)

            Call fnDetenerTiempo(GBLTiempoDos)

     

        Next c

     

    End Function

     

    Private Sub sbEntradas(ByVal i As Integer)    

    Dim sintciclo As Integer

    Dim chksum    As Integer

    Dim j As Byte

    Dim indx As Byte

     

     If i >= 24 Then

        i = 0

     End If

     

     GBLTipo = "ENTRADA"

     protocolo__TX(0) = &H1

     protocolo__TX(1) = CByte(GBLEstatusTorreta(GBLCiclo).Torreta)

     protocolo__TX(2) = &H0

     protocolo__TX(3) = &H3C

     protocolo__TX(4) = i  'entrada que se quiere leer

     For j = 5 To 19 Step 1

       protocolo__TX(j) = 0

     Next j

     chksum = 0

     For indx = 0 To 19 Step 1

       chksum = chksum + protocolo__TX(indx)

     Next indx

     chksum = chksum And 255

     chksum = chksum Xor 255

     chksum = chksum + 1

     protocolo__TX(20) = CByte(chksum And &HFF)

      'Envia los datos por el puerto serial

     For indx = 0 To 20 Step 1

          MSComm1.Output = Chr(protocolo__TX(indx))

     Next indx

    End Sub

     

    Public Function fnDetenerTiempo(ByVal TicksEsperando As Long)

    Dim TicksIniciales As Long

    TicksIniciales = GetTickCount() + TicksEsperando

    Do While TicksIniciales > GetTickCount()

    DoEvents

    Loop

    End Function

     

    Public Function fnDetenerTiempoDos(ByVal TicksEsperando As Long)

    Dim TicksIniciales As Long

    TicksIniciales = GetTickCount() + TicksEsperando

    Do While TicksIniciales > GetTickCount()

    Loop

    End Function

    Las propiedad interval del Timer es de 1000 y Enabled= False (la propiedad enabled la enciendo en el load ),
    La variable GBLtiempo = 1000
    ""              GBLtiempoDos= 300
    Me comentaban que le detalle podría ser porque tengo declaradas variables detro del metodo del Timer, porque según esto esas variables no se destruyen en tiempo de ejecución o cuando abandona el evento Timer y me recomendarón aplicar un Nothing y declarar las variables en la clase osea fuera del metodo Timer.
    Espero me puedan ayudar de antemano mil Gracias!!

    lunes, 25 de julio de 2011 12:28

Todas las respuestas

  • Saludos

    Puede ser que tu Procedimiento fnRecorrerentradas demore mas de un segundo y antes que termine el timer lanza una segunda llamada, es posible que después de un tiempo las llamadas se interpongan, si ocurre esto, imagino que el puerto serial se mantiene ocupado cada vez más tiempo en procesar las solicitudes de la cola, mientras tanto el timer sigue enviado nuevas peticiones cada nuevo segundo. Es una idea.

    Saludos
    CarloCF

     

     

    viernes, 29 de julio de 2011 4:53
  • Saludos

    Puede ser que tu Procedimiento fnRecorrerentradas demore mas de un segundo y antes que termine el timer lanza una segunda llamada, es posible que después de un tiempo las llamadas se interpongan, si ocurre esto, imagino que el puerto serial se mantiene ocupado cada vez más tiempo en procesar las solicitudes de la cola, mientras tanto el timer sigue enviado nuevas peticiones cada nuevo segundo. Es una idea.

    Saludos
    CarloCF

     

     

    Ok me parece bién la perspectiva de lo que pueda estar causando este problema, pero como sería la solución? le doy más interval al Timer? o le doy más segundos a las funciones encargadas de detener el tiempo para el envio de datos?. alguna idea que puedas sugerir? agradezco tu ayuda.

    GRACIAS!

    viernes, 29 de julio de 2011 14:51
  • Imagino (no revisé el código que colocas) que utilizas los temporizadores para revisar el objeto comm_control.

    Mejor utiliza el evento oncomm, que se dispara cuando llega data. Por mas que he buscado, no he encontrado información clara, sin embargo, lo utilizo para comunicarme con un modem sms sin problema.

    Te pego aquí código que tomé de un ejemplo (no recuerdo de donde).

    Private Sub GsmComm_OnComm()
    Debug.Print GsmComm.Input
    Select Case GSMComm.CommEvent
            '"Mensajes relativos a sucesos
            Case comEvReceive
                'RecibirCom
               
            Case comEvSend
                evmsg = "Por ahora no hago nada"
            Case comEvCTS
                evmsg = "Cambio detectado en CTS"
            Case comEvDSR
                evmsg = "Cambio detectado en DSR"
            Case comEvCD
                evmsg = "Cambio detectado en DCD"
            Case comEvRing
                evmsg = "El teléfono está sonando"
            Case comEvEOF
                evmsg = "Fin de fichero"

            '"Mensajes de error
            Case comBreak
                evmsg = "Interrupción detectada"
            Case comCTSTO
                ERMsg = "Tiempo para CTS sobrepasado"
            Case comDSRTO
                ERMsg = "Tiempo para DSR sobrepasado"
            Case comFrame
                evmsg = "Error de transmisión (encuadre)"
            Case comOverrun
                ERMsg = "Error de sobrescritura"
            Case comCDTO
                ERMsg = "Tiempo para DCD sobrepasado"
            Case comRxOver
                ERMsg = "Buffer de recepción lleno"
            Case comRxParity
                evmsg = "Error de paridad"
            Case comTxFull
                ERMsg = "Buffer de transmisión lleno"
            Case Else
                ERMsg = "Error o suceso desconocido"
        End Select
    End Sub

    viernes, 29 de julio de 2011 23:42
  • Hola

    En este punto creo que debes probar y ver si resulta. Adicionalmente guarracuco te sugiere un evento y el codigo de muestra. Yo haria tanteo y error para ver por donde se decanta el problema con las correcciones. Esperamos tus noticias

    Saludos

    CarloCF

    sábado, 30 de julio de 2011 2:54
  • claro guarracuco eso es lo que hago en el On_Common  hay es donde hago ciertas operaciones para recibir la información las funciones de detención del tiempo las hago después que mando el protocolo de comunicación para que de esta manera se vayan los comandos de uno en uno y después me responde de la misma manera con un protocolo parecido.

     CommEvent = ComEvReceive estos metodos los utilizo para cuando reciba el dato después actue sobre los mismos.

     

     

     

    martes, 2 de agosto de 2011 14:29
  • Bueno CarloCF  me comentarón que podía dividir mi aplicación en 2 partes lo que pasa es que en una parte del protocolo de comunicación tengo que recibir 23 datos uno en uno, después con esos datos yo los manipulo y hago updates a una BD en MySQL, pero esto se hace con los 23 datos osea estamos hablando de demasiados updates en un segundo y aparte hace unas comparaciones para enviar e-mails si esa información es correspondiente con la de la BD, el envio de correos lo hago por SMTP.

     

    Me comentabas anteriomente que quiza la función que tenia demoraba más tiempo que 1 segundo y si tenias razón daba un tick cada 23 ocasiones entonces opte por meter el protocolo de comunicación directo en el Timer en el evento Tick y ahora si por cada petición que hace se realiza un tick y aumenta esa variable, el detalle es lo que te comento que estoy sobresaturando las funciones y mi aplicación con los updates y compraraciones.

     

    Me propusierón hacer esto: que generara un .exe que solo actualizara(por medio de store procedure´s y cosas demás) por un cierto tiempo(10 minutos ) después de pasar ese tiempo la aplicación se cierra, cuando se cierra se abre el otro .exe que solo se encargará de obtener los registros que me arroja el protocolo de comunicación una vez que termine de vaciar la información se cerrará y vuelvo a abrir el .exe que se encarga de actualizar los datos en tiempo real, para vaciar los datos no toma menos de 3 minutos asi que por ese lado pienso que la información estaria casi actual de lo que esta sucediendo.

    los comandos para la obtención de datos y lectura de los mimos son diferentes que el comando que me manda la información en tiempo real, así que por ese lado no hay problema.

    Nota: me comentarón también que esto lo podia realizar por medio del programador de tareas de windows.

    Espero y puedan comentar acerca de esta propuesta.!

    Saludos y Gracias!

    martes, 2 de agosto de 2011 14:42
  • Nerk10, si sigues lo comentado por CarloCF de almacenar en un buffer o arreglo o tablita lo que vá llegando? y un proceso paralelo (otra exe) realiza las operaciones? la cuestión está (al menos para mí) que solo tu tienes un panorama claro del proceso.
    martes, 2 de agosto de 2011 22:16