none
Problemas con ejecución de Hilo RRS feed

  • Pregunta

  • Hola, espero todo se encuentre bien con ustedes.

    Resulta que en mi trabajo me solicitan cambiar una bitácora de un archivo plano a que se registre en una BD la cual es oracle pero además tenemos unas restricciones de tiempo por lo cual lo ideal es que el registro de la bitacora se maneje en un hilo aparte para que este proceso no consuma los milisegundos o segundos que gaste.

    Hasta este punto todo bien, realice un procedimiento almacenado y si lo pruebo sin el uso de hilos este registra en la BD los datos.

    El problema lo tengo cuando quiero hacerlo por medio de hilos ya que no registra nada en la tabla.

    Les dejo el código con el que lo realizo para ver si me pueden iluminar en lo que me falte.

    Dentro de una clase cree una variable y su accesibilidad es private y se llama:

    Dim vHiloBitacora As Thread

    Cree un sub llamado RegistrarBitacora()

    Public Sub RegistrarBitacora()
            Dim vParametros As String = ""
            Try
                For i = 0 To vListaParametro.Count - 1
                    vParametros = vParametros + vListaParametro(i).ObtenerNombreParametro + "=" + vListaParametro(i).ObtenerDato + ";"
                Next
                vDatoBitacora = "Se inicia el llamado del procedimiento " + vProcedimiento + " con los siguientes parámetros de entrada: " + vParametros + ";" + Chr(13)
                If String.IsNullOrEmpty(vErrorRegistrarBitacora) Then
                    vDatoBitacora = vDatoBitacora + "Error: " + vErrorRegistrarBitacora + ";" + Chr(13)
                End If
                vDatoBitacora = vDatoBitacora + "Se envía el siguiente XML: " + vXMLBitacora + ";" + Chr(13)
                vDatoBitacora = vDatoBitacora + "Finaliza el llamado del procedimiento sinpe.sp_procs.SP_ACREDITAR_CUENTA con los siguientes parámetros de entrada: " + vParametros + ";" + Chr(13)
                vConexion.RegistrarBitacora("esquema.nombrePaquete.SP_REGISTRAR_BITACORA_WS", vDatoBitacora)
            Catch ex As Exception

            End Try
        End Sub

    y cuando quiero llamar al hilo lo realizo por medio de este:

    Public Sub CrearHilo()
            vHiloBitacora = New Thread(AddressOf RegistrarBitacora)
            vHiloBitacora.IsBackground = True
            vHiloBitacora.Start()
        End Sub

    Otra cosa, cuando lo debugueo y voy paso por paso por CrearHilo nunca me manda al procedimiento de RegistrarBitacora para saber que está saliendo mal.

    Agradezco la ayuda que puedan brindarme.

    martes, 9 de agosto de 2016 16:06

Respuestas

  • Gracias por la respuesta Enrique.

    Ya encontré el problema, resulta que yo concateno en la variable vDatoBitacora texto y le concateno chr(13) que es el enter y no se por que la BD no lo registra.

    Le agradezco toda la colaboración y de igual manera analizaré sus consejos para ver si puedo aplicarlos en este proyecto.

    Saludos.

    miércoles, 10 de agosto de 2016 20:07

Todas las respuestas

  • Otra cosa que agregrar es que el hilo si inicia su ejecución ya que si retorno a pantalla el campo vDatoBitacora se muestran todos los datos con el que se llena esa variable en el sub RegistrarBitacora, es decir lo único que no hace es la línea vConexion.RegistrarBitacora("esquema.nombrePaquete.SP_REGISTRAR_BITACORA_WS", vDatoBitacora) donde vConexion es una clase que se instancia y que es el contenedor del método RegistrarBitacora.
    martes, 9 de agosto de 2016 19:48
  • "Randall Castro" escribió:

    > Public Sub RegistrarBitacora()
    >
    >    Try
    >        ' código de ejecución.
    >
    >        ...
    >
    >        vDatoBitacora = vDatoBitacora + "Finaliza el llamado del procedimiento sinpe.sp_procs...
    >        vConexion.RegistrarBitacora("esquema.nombrePaquete.SP_REGISTRAR_BITACORA_WS", vDatoBitacora)
    >
    >   Catch ex As Exception
    >
    >   End Try
    >
    > End Sub

    Hola:

    Estoy observando que en el procedimiento RegistrarBitacora tienes insertado un bloque Try ... Catch ... End Try, el cual tiene su bloque Catch completamente en blanco. La verdad es que ignoro por completo para qué quieres un bloque Catch en blanco, ya que deberías de saber que si se produce un error en el código que ejecutas en el bloque Try, NUNCA te enterarás del error que se ha podido producir.

    > ... el hilo si inicia su ejecución ya que si retorno a pantalla el campo vDatoBitacora
    > se muestran todos los datos con el que se llena esa variable en el sub RegistrarBitacora,
    > es decir lo único que no hace es la línea Conexion.RegistrarBitacora
    > "esquema.nombrePaquete.SP_REGISTRAR_BITACORA_WS", vDatoBitacora) donde vConexion es una
    > clase que se instancia y que es el contenedor del método RegistrarBitacora.

    Si dices que NO SE EJECUTA la línea Conexion.RegistrarBitacora (...), ¿no puedes pensar en que se haya producido un error en alguna línea de código ANTES de la llamada al procedimiento RegistrarBitacora de la clase Conexion? Si ha sido así, y al tener el bloque Catch en blanco, tu mismo estás anulando por completo sin darte cuenta el error producido, y lo peor de todo es que no te enterarás del motivo por el cual se ha producido.

    Si tu intención es dejar el bloque Catch en blanco, mejor será que NO ENCIERRES el código de ejecución entre un bloque Try ... Catch ... End Try, pero si lo encierras, lo correcto es que escribas el código de depuración adecuado en el bloque Catch.

    En principio y mientras te encuentras depurando tu aplicación, mi consejo sería que en el bloque Catch insertaras el clásico cuadro de mensaje para comprobar si has obtenido o no un error:

        Public Sub RegistrarBitacora()
    
            Try
                ' código de ejecución.
    
                ' ...
    
                vDatoBitacora = vDatoBitacora + "Finaliza el llamado del procedimiento sinpe.sp_procs...
                vConexion.RegistrarBitacora("esquema.nombrePaquete.SP_REGISTRAR_BITACORA_WS", vDatoBitacora)
    
    ' Eliminar la siguiente línea cuando el código esté completamente depurado.
    MessageBox.Show("El registro de la bitácora se ha realizado satisfactoriamente.")
    Catch ex As Exception ' Se ha producido una excepción; mostramos el mensaje de error. MessageBox.Show(ex.Message) End Try End Sub

    Si observas que no tienes ningún error y se ha mostrado el mensaje "El registro de la bitácora se ha realizado satisfactoriamente", entonces puedes quitar el bloque Try ... Catch ... End Try si así lo deseas, aunque yo no voy a ser el que te aconseje que lo hagas. ;-)

    Y si se ha producido un error, sabrás el motivo por el cual no se ha ejecutado la línea Conexion.RegistrarBitacora (...).

    Un saludo


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.




    miércoles, 10 de agosto de 2016 5:20
    Moderador
  • Gracias Enrique por los consejos.

    Lo que sucede es que eso se encuentra en un Web Services por lo que no muestro ese mensaje. Lo del try catch lo hago tengo por que si falla algo en ese procedimiento pues debo registrar el error en un archivo plano pero aún no desarrollo eso. Además al hacer el debug no entra al catch.

    Sin embargo lo que hice es que el WS me retorne un string y que ese string muestre vdatoBitacora el cual se llena con texto antes y despues del método sp_registrar_bitacora y efectivamente me muestra todo el texto pero no me registra nada en la BD por eso sé que el hilo se ejecuta.

    Sp_registrar_bitacora pertenece a otra clase y el método es público y por supuesto que instancié la clase para llamarlo.

    Por otro lado si llamo ese método sp_registrar_bitacora fuera del hilo si me registra los datos en la BD.

    El método sp_registrar_bitacora es sencillo:

    'Registra en la bitácora de los web services sp_bitacora_web_services
        Public Sub RegistrarBitacora(ByVal pNombreProcedimiento As String, ByVal pBitacora As String)
            Try
                conectar()
                Dim vAdapter As New OracleDataAdapter
                Dim vComando As New OracleCommand
                Dim param As New OracleParameter
                vComando.Connection = vOraCon
                vComando.CommandText = "esquema.nombre_paquete.SP_REGISTRAR_BITACORA_WS"
                vComando.CommandType = CommandType.StoredProcedure
                vComando.Parameters.Add("pvDetalle", OracleDbType.Varchar2).Value = pBitacora
                vAdapter.SelectCommand = vComando
                vComando.ExecuteNonQuery()
                cerrarConexion()
            Catch ex As OracleException
                vError = "Problemas al cerrar bitacora. Oracle Exception: " + ex.Message
                vEscribirLog.escribirLog("Problemas cerrando la conexion. Oracle Exception: " + ex.Message + " / " + ex.StackTrace)
            Catch ex As NullReferenceException
                vError = "Problemas al cerrar bitacora. Null Reference " + ex.Message + " / " + ex.StackTrace
                vEscribirLog.escribirLog("Problemas cerrando la conexion. Null Reference " + ex.Message + " / " + ex.StackTrace)
            Catch ex As Exception
                vError = ex.Message
                vError = "Problemas al cerrar bitacora cayó en la excepción general" + ex.Message + " / " + ex.StackTrace
                cerrarConexion()
                vEscribirLog.escribirLog("Problemas al cerrar bitacora" + ex.Message + " / " + ex.StackTrace)
            End Try
        End Sub

    miércoles, 10 de agosto de 2016 16:14
  • "Randall Castro" escribió:

    > Lo que sucede es que eso se encuentra en un Web Services por lo que no muestro ese mensaje.
    > Lo del try catch lo hago tengo por que si falla algo en ese procedimiento pues debo registrar
    > el error en un archivo plano pero aún no desarrollo eso. Además al hacer el debug no entra al
    > catch.
    >

    Si se ha producido un error y el bloque Catch está completamente en blanco (no existe código fuente alguno), va a ser complicado que el bloque de ejecución del código entre en dicho bloque, simplemente porque NO EXISTE CÓDIGO PARA EJECUTAR: tan solo estarás ANULANDO la excepción que se haya podido producir. De ahí que no se aconseje tener bloques Catch "en blanco", salvo que seas completamente consciente de ello y lo hallas colocado expresamente para anular cualquier excepción producida, claro está.

    > Public Sub RegistrarBitacora(ByVal pNombreProcedimiento As String, ByVal pBitacora As String)

    Según he entendido de tu respuesta, ese procedimiento se encuentra en un Web Service, y sus bloques Catch tienen su correspondiente código.

    >     Catch ex As OracleException
    >             vError = "Problemas al cerrar bitacora. Oracle Exception: " + ex.Message
    >             vEscribirLog.escribirLog("Problemas cerrando la conexion. Oracle Exception: " + ex.Message + " / " + ex.StackTrace)
    >         Catch ex As NullReferenceException
    >             vError = "Problemas al cerrar bitacora. Null Reference " + ex.Message + " / " + ex.StackTrace
    >             vEscribirLog.escribirLog("Problemas cerrando la conexion. Null Reference " + ex.Message + " / " + ex.StackTrace)
    >         Catch ex As Exception
    >             vError = ex.Message
    >             vError = "Problemas al cerrar bitacora cayó en la excepción general" + ex.Message + " / " + ex.StackTrace
    >             cerrarConexion()
    >             vEscribirLog.escribirLog("Problemas al cerrar bitacora" + ex.Message + " / " + ex.StackTrace)
    >         End Try

    Observo que los bloques Catch tienen código de ejecución, quizás para escribir el error producido en la bitácora. Pero si te fijas bien, también estás ANULANDO la excepción producida, ya que no estás devolviendo la excepción al procedimiento cliente que ha invocado al método RegistrarBitacora del Web Service.

    Para devolver la excepción tendrías que llamar a la instrucción Throw en los tres bloques Catch inmediatamente después de haber escrito en la bitácora, para devolverle al cliente el error producido, cosa que yo no soy partidario de ello porque es en el código cliente donde tienes que CAPTURAR LOS POSIBLES ERRORES que se produzcan en dicho procedimiento. Es decir, esos tres bloques Catch deberían estar en el procedimiento que llama al método RegistrarBitacora(ByVal pNombreProcedimiento As String, ByVal pBitacora As String).

    > Public Sub RegistrarBitacora()

    Pero el procedimiento RegistrarBitacora (sin parámetros en su firma), ¿dónde se encuentra? Si se trata de otro procedimiento diferente a aquel que con el mismo nombre dices que tienes en un Web Service, entiendo que lo CORRECTO sería que insertaras en su bloque Catch algún cuadro de mensaje para saber si obtienes o no un error.

    ¿Has probado a ponerle el MessageBox.Show que te indiqué en mi respuesta anterior? Solamente quiero que me respondas Sí o No, y si has obtenido o no un error.


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.



    miércoles, 10 de agosto de 2016 16:59
    Moderador
  • Gracias por la respuesta Enrique.

    Ya encontré el problema, resulta que yo concateno en la variable vDatoBitacora texto y le concateno chr(13) que es el enter y no se por que la BD no lo registra.

    Le agradezco toda la colaboración y de igual manera analizaré sus consejos para ver si puedo aplicarlos en este proyecto.

    Saludos.

    miércoles, 10 de agosto de 2016 20:07