none
Ayúdenme con este error en mi aplicación VB.NET RRS feed

  • Pregunta

  • He creado una aplicación para controlar asistencia de trabajadores con código QR,  y cada media hora o 2 horas aleatoria mente se detiene y muestra el siguiente error. 

    ************** Texto de la excepción **************

    System.InvalidOperationException: El objeto ya está en uso.

       en System.Drawing.Graphics.CheckErrorStatus(Int32 status)

       en System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y, Int32 width, Int32 height)

       en System.Drawing.Graphics.DrawImage(Image image, Rectangle rect)

       en System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)

       en System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)

       en System.Windows.Forms.Control.WmPaint(Message& m)

       en System.Windows.Forms.Control.WndProc(Message& m)

       en System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)

       en System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)

       en System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

    Mi código fuente es este :

    ----------------------------

    Private Sub video_NuevoFrame2(sender As Object, eventArgs As NewFrameEventArgs)

            'PRESENTA LAS IMAGENES EN EL PICTUREBOX1

            Try

                IMAGEN2 = TryCast(eventArgs.Frame.Clone(), Bitmap)

                PictureBox4.Image = IMAGEN2

            Catch ex As Exception

            End Try

        End Sub

    Anteriormente me sugirieron esta solución: 

    Private Sub video_NuevoFrame1(sender As Object, eventArgs As NewFrameEventArgs)
        Me.Invoke(Sub() 
             'PRESENTA LAS IMAGENES EN EL PICTUREBOX1
             Try
                 IMAGEN = TryCast(eventArgs.Frame.Clone(), Bitmap)
                 PictureBox1.Image = IMAGEN
             Catch ex As Exception
                 PictureBox1.Refresh()
             End Try
         End Sub)
    End Sub

    Hasta el momento no se presentan errores, pero la imagen de la cámara se muestra en cámara lenta, he perdido muchos FPS, y parece que mi aplicación esta consumiendo muchos mas recursos que antes.

    Alguien podría ayudarme. por favor

    lunes, 15 de julio de 2019 16:51

Respuestas

  • Has olvidado mencionar un dato vital, y es que estás trabajando en multi-hilo. De lo contrario no necesitarías el Me.Invoke.

    La cuestión es que la interfaz de usuario en las aplicaciones de escritorio es mono-hilo. No soporta que la interfaz se modifique desde un hilo distinto del que la creó. Si lo intentas, en principio parece que "no pasa nada", pero cuando da la casualidad de que dos hilos coinciden a la vez en modificar la misma estructura interna, esta estructura se corrompe y suceden errores aleatorios e imprevisibles (como te está ocurriendo).

    Para evitarlo, se usa el método Invoke, como en la solución que te sugirieron. Lo que hace es esperar a que el hilo principal no esté ocupado, y entonces ejecuta el código que le hayas pasado como argumento, dentro del hilo principal. Claro, si en el hilo principal estás haciendo otras cosas a la vez, entonces cuando tiene que esperar a que no esté ocupado se pierde velocidad, que en tu caso notas como "pérdida de frames". Incluso aunque no esté ocupado, el hecho de que se tenga que transportar la ejecución entre hilos también perjudica la velocidad.

    Para reducir este efecto lo más posible, reduce al mínimo lo que hagas dentro del Invoke. Deja únicamente lo que afecte a la pantalla, en este caso PictureBox1.Image = IMAGEN, y todo lo demás hazlo fuera del Invoke.

    • Propuesto como respuesta Pablo Rubio miércoles, 17 de julio de 2019 21:39
    • Marcado como respuesta Ricardo_raf7 jueves, 25 de julio de 2019 17:33
    lunes, 15 de julio de 2019 20:56

Todas las respuestas

  • Has olvidado mencionar un dato vital, y es que estás trabajando en multi-hilo. De lo contrario no necesitarías el Me.Invoke.

    La cuestión es que la interfaz de usuario en las aplicaciones de escritorio es mono-hilo. No soporta que la interfaz se modifique desde un hilo distinto del que la creó. Si lo intentas, en principio parece que "no pasa nada", pero cuando da la casualidad de que dos hilos coinciden a la vez en modificar la misma estructura interna, esta estructura se corrompe y suceden errores aleatorios e imprevisibles (como te está ocurriendo).

    Para evitarlo, se usa el método Invoke, como en la solución que te sugirieron. Lo que hace es esperar a que el hilo principal no esté ocupado, y entonces ejecuta el código que le hayas pasado como argumento, dentro del hilo principal. Claro, si en el hilo principal estás haciendo otras cosas a la vez, entonces cuando tiene que esperar a que no esté ocupado se pierde velocidad, que en tu caso notas como "pérdida de frames". Incluso aunque no esté ocupado, el hecho de que se tenga que transportar la ejecución entre hilos también perjudica la velocidad.

    Para reducir este efecto lo más posible, reduce al mínimo lo que hagas dentro del Invoke. Deja únicamente lo que afecte a la pantalla, en este caso PictureBox1.Image = IMAGEN, y todo lo demás hazlo fuera del Invoke.

    • Propuesto como respuesta Pablo Rubio miércoles, 17 de julio de 2019 21:39
    • Marcado como respuesta Ricardo_raf7 jueves, 25 de julio de 2019 17:33
    lunes, 15 de julio de 2019 20:56
  • Muchas gracias por responder, voy a intentarlo ahora mismo.
    miércoles, 17 de julio de 2019 13:15
  • Has olvidado mencionar un dato vital, y es que estás trabajando en multi-hilo. De lo contrario no necesitarías el Me.Invoke.

    La cuestión es que la interfaz de usuario en las aplicaciones de escritorio es mono-hilo. No soporta que la interfaz se modifique desde un hilo distinto del que la creó. Si lo intentas, en principio parece que "no pasa nada", pero cuando da la casualidad de que dos hilos coinciden a la vez en modificar la misma estructura interna, esta estructura se corrompe y suceden errores aleatorios e imprevisibles (como te está ocurriendo).

    Para evitarlo, se usa el método Invoke, como en la solución que te sugirieron. Lo que hace es esperar a que el hilo principal no esté ocupado, y entonces ejecuta el código que le hayas pasado como argumento, dentro del hilo principal. Claro, si en el hilo principal estás haciendo otras cosas a la vez, entonces cuando tiene que esperar a que no esté ocupado se pierde velocidad, que en tu caso notas como "pérdida de frames". Incluso aunque no esté ocupado, el hecho de que se tenga que transportar la ejecución entre hilos también perjudica la velocidad.

    Para reducir este efecto lo más posible, reduce al mínimo lo que hagas dentro del Invoke. Deja únicamente lo que afecte a la pantalla, en este caso PictureBox1.Image = IMAGEN, y todo lo demás hazlo fuera del Invoke.

    Gracias tu propuesta fue la mejor solución, quedo muy agradecido...
    jueves, 25 de julio de 2019 17:33