Foros del Web » Programación para mayores de 30 ;) » .NET »

Se me cuelga Windows Form

Estas en el tema de Se me cuelga Windows Form en el foro de .NET en Foros del Web. ola: Tengo un programa que recibe datos una y otra vez por el puerto serie. A 0.1 segundos datos del 0 al 1023. Si no ...
  #1 (permalink)  
Antiguo 27/04/2016, 04:01
 
Fecha de Ingreso: mayo-2007
Ubicación: PIC-16F84A
Mensajes: 727
Antigüedad: 16 años, 10 meses
Puntos: 8
Se me cuelga Windows Form

ola:

Tengo un programa que recibe datos una y otra vez por el puerto serie. A 0.1 segundos datos del 0 al 1023. Si no hay datos que esté leyendo porque en el otro lado no lo está enviando, puedo cerrar el programa sin problemas. Si hay datos que le llega y lee, al cerrar el programa aunque pongas SerialPort1.Close(); El programa se cuelga.

En el Load de Windwos Form he puesto esto.
Código C:
Ver original
  1. Control.CheckForIllegalCrossThreadCalls = false;
https://msdn.microsoft.com/es-es/lib...vs.100%29.aspx

Se sigue colgando. No ha funcionado.

Por lo que he leído hay que usar hilos y es más complejo, no lo se.

¿Alguna solución?

Enlace del proycto en Visual Studio Community 2015.

Descargar

Saludos.
__________________
Meta Shell, VERSIÓN 1.2.2
Descargar
  #2 (permalink)  
Antiguo 27/04/2016, 04:14
Avatar de Malenko
Moderador
 
Fecha de Ingreso: enero-2008
Mensajes: 5.323
Antigüedad: 16 años, 3 meses
Puntos: 606
Respuesta: Se me cuelga Windows Form

Tiene toda la pinta de que haya un bug en tu código y estás bloqueando al thread principal.

Solución: todo la lógica de negocio (sobre todo si tiene operaciones bloqueantes, como las de I/O) se han de ejecutar en una task o thread independiente.
__________________
Aviso: No se resuelven dudas por MP!
  #3 (permalink)  
Antiguo 27/04/2016, 04:55
 
Fecha de Ingreso: mayo-2007
Ubicación: PIC-16F84A
Mensajes: 727
Antigüedad: 16 años, 10 meses
Puntos: 8
Respuesta: Se me cuelga Windows Form

Hola:

Llevo dos meses con esto, volví a la carga que ni en MSDN logran la solución.

https://social.msdn.microsoft.com/Fo...rm?forum=vcses

Tiene que haber alguien en el mundo que sepa como solucionarlo.

Saludos.
__________________
Meta Shell, VERSIÓN 1.2.2
Descargar
  #4 (permalink)  
Antiguo 27/04/2016, 05:01
Avatar de Malenko
Moderador
 
Fecha de Ingreso: enero-2008
Mensajes: 5.323
Antigüedad: 16 años, 3 meses
Puntos: 606
Respuesta: Se me cuelga Windows Form

Ya te he dicho la solución: realiza el procesamiento del puerto serie en un thread/Task diferente al thread principal de la aplicación.
__________________
Aviso: No se resuelven dudas por MP!
  #5 (permalink)  
Antiguo 27/04/2016, 05:04
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: Se me cuelga Windows Form

Ok...

Haznos un favor: Toma el código que subiste a ese repositorio y postealo aqui. AL menos lo referente a ese WinForm.
Bajar un proyecto ajeno para debuggearlo, sin saber qué tan seguro es, e incluso gratuitamente, no es la meta del foro. La idea es que consultes problemas concretos y nos muestres los códigos que te solicitamos.

Copia el codigo aquí, con los Highlights correspondientes.
Luego veremos.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #6 (permalink)  
Antiguo 27/04/2016, 08:34
 
Fecha de Ingreso: mayo-2007
Ubicación: PIC-16F84A
Mensajes: 727
Antigüedad: 16 años, 10 meses
Puntos: 8
Respuesta: Se me cuelga Windows Form

Holaaaaaaaa:

El program.cs es el típico que viene.
Código:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Arduino_In_Analogico_prueba_01
{
    static class Program
    {
        /// <summary>
        /// Punto de entrada principal para la aplicación.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}
El código completo es este.
Código:
using System;
using System.Collections.Generic;
using System.Windows.Forms;

using System.IO.Ports; // No olvidar.
using System.IO;

namespace Arduino_In_Analogico_prueba_01
{
    public partial class Form1 : Form
    {
        // Utilizaremos un string como buffer de recepción.
        string Recibidos;

        public Form1()
        {
            InitializeComponent();

            if (!serialPort1.IsOpen)
            {
                try
                {
                    serialPort1.Open();
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }

                serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
            }

            
        }

        // Al recibir datos.
        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {

            // Acumula los caracteres recibidos a nuestro 'buffer' (string).
            try
            {
                Recibidos = serialPort1.ReadLine();
            }

            catch (IOException)
            {
                // Información adicional: La operación de E/S se anuló por una salida de subproceso o por una solicitud de aplicación.
            }

            // Invocar o llamar al proceso de tramas.
            Invoke(new EventHandler(Actualizar));
        }


        // Como variables de clase
        private string[] Separador = new string[] { ",", "\r", "\n", "/n" };
        private List<string> Leo_Dato = new List<string>();

        // Procesar los datos recibidos en el bufer y extraer tramas completas.
        private void Actualizar(object sender, EventArgs e)
        {
            double Voltaje = 0;
            double Porcentaje = 0;

            // En el evento
            Leo_Dato.Clear();
            Leo_Dato.AddRange(Recibidos.Split(Separador, StringSplitOptions.RemoveEmptyEntries));

            //            Se produjo una excepción de tipo 'System.ArgumentOutOfRangeException' en mscorlib.dll pero no se controló en el código del usuario


            try
            {
                label_Lectura_Potenciometro.Text = Leo_Dato[0].ToString();
            }

            catch (ArgumentOutOfRangeException)
            {
                //Información adicional: El índice estaba fuera del intervalo. Debe ser un valor no negativo e inferior al tamaño de la colección.
            }


            progressBar1.Value = Convert.ToInt32(Leo_Dato[0].ToString());
            double Dato_Voltaje = Convert.ToDouble(Leo_Dato[0]);
            double Dato_Porcentaje = Convert.ToDouble(Leo_Dato[0]);

            Voltaje = Dato_Voltaje * (5.00 / 1023.00);
            Porcentaje = Dato_Porcentaje * (100.00 / 1023.00);

            label_Voltio.Text = Voltaje.ToString("N2") + " V."; // N2 tiene dos decimales.
            label_Portentaje.Text = Porcentaje.ToString("N2") + " %";
        }
    }
}
Saludos.
__________________
Meta Shell, VERSIÓN 1.2.2
Descargar
  #7 (permalink)  
Antiguo 27/04/2016, 08:59
Avatar de Malenko
Moderador
 
Fecha de Ingreso: enero-2008
Mensajes: 5.323
Antigüedad: 16 años, 3 meses
Puntos: 606
Respuesta: Se me cuelga Windows Form

A ese código solo tienes que aplicar lo que te comenté más arriba para solucionar el problema.
__________________
Aviso: No se resuelven dudas por MP!
  #8 (permalink)  
Antiguo 27/04/2016, 10:09
 
Fecha de Ingreso: mayo-2007
Ubicación: PIC-16F84A
Mensajes: 727
Antigüedad: 16 años, 10 meses
Puntos: 8
Respuesta: Se me cuelga Windows Form

Hola Señor Malenko:

Lo se, pero tengo peros. Falta conocimiento. Ahora buscando información primero.
https://msdn.microsoft.com/es-es/lib...or=-2147217396

https://msdn.microsoft.com/es-es/library/hh191443.aspx

Me queda mucho por leer, intentar conseguir entener para empezar hacer pequeñas pruebas de códigos.

Dejo claro que si el puerto serie deja de recibir datos, si puedo cerrar el programa sin problemas.

Lo que se me ocurre que al cerrar el programa, envío un comando al puerto serie que en el otro lado lo entienda para que deje de entregar datos y luego cierra. Como último recurso lo haré así, más bien lo dejaré así.

Saludos.
__________________
Meta Shell, VERSIÓN 1.2.2
Descargar
  #9 (permalink)  
Antiguo 27/04/2016, 10:12
Avatar de Malenko
Moderador
 
Fecha de Ingreso: enero-2008
Mensajes: 5.323
Antigüedad: 16 años, 3 meses
Puntos: 606
Respuesta: Se me cuelga Windows Form

Repito, busca información sobre el uso de Task o Threads. No te hace falta Async/Await.

Yo ahora mismo estoy actualizando un proyecto que monté para un hospital con un Arduino y que lee los datos mediante puerto serie con un Windows Form y lo he hecho como te estoy diciendo y cero problemas.
__________________
Aviso: No se resuelven dudas por MP!
  #10 (permalink)  
Antiguo 27/04/2016, 10:43
 
Fecha de Ingreso: mayo-2007
Ubicación: PIC-16F84A
Mensajes: 727
Antigüedad: 16 años, 10 meses
Puntos: 8
Respuesta: Se me cuelga Windows Form

Cita:
Iniciado por Malenko Ver Mensaje
Repito, busca información sobre el uso de Task o Threads. No te hace falta Async/Await.

Estoy en ello.


Yo ahora mismo estoy actualizando un proyecto que monté para un hospital con un Arduino y que lee los datos mediante puerto serie con un Windows Form y lo he hecho como te estoy diciendo y cero problemas.
Dejo claro que solo me pasa cuando recibe muchos datos uno tras otro por el puerto serie, si es poco no pasa nada, aquí y aquí ejemplos que he hecho sobre Visual Studio en general, pero no usando analógicos, que estoy en ello para hacer otros documentos como indiqué.

Saludos.

PD: Si estás haciendo eso en el hostipal, estás hecho un profesional.
__________________
Meta Shell, VERSIÓN 1.2.2
Descargar
  #11 (permalink)  
Antiguo 01/05/2016, 01:43
 
Fecha de Ingreso: mayo-2007
Ubicación: PIC-16F84A
Mensajes: 727
Antigüedad: 16 años, 10 meses
Puntos: 8
Respuesta: Se me cuelga Windows Form

Hola:

Ahora añadí un timer que lee a 1000 ms frente a los 100 ms que envía Arduino.

Se me cuelga a veces, antes era siempre.

Código C:
Ver original
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows.Forms;
  4.  
  5. using System.IO.Ports; // No olvidar.
  6. using System.IO;
  7.  
  8. namespace Arduino_In_Analogico_prueba_01
  9. {
  10.     public partial class Form1 : Form
  11.     {
  12.         // Utilizaremos un string como buffer de recepción.
  13.         string Recibidos;
  14.  
  15.         public Form1()
  16.         {
  17.             InitializeComponent();
  18.  
  19.             if (!serialPort1.IsOpen)
  20.             {
  21.                 try
  22.                 {
  23.                     serialPort1.Open();
  24.                 }
  25.                 catch (System.Exception ex)
  26.                 {
  27.                     MessageBox.Show(ex.ToString());
  28.                 }
  29.  
  30.                 serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
  31.             }
  32.         }
  33.  
  34.  
  35.         // Al recibir datos.
  36.         private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
  37.         {
  38.  
  39.             // Acumula los caracteres recibidos a nuestro 'buffer' (string).
  40.             try
  41.             {
  42.                 // Recibidos = serialPort1.ReadLine();
  43.             }
  44.  
  45.             catch (IOException)
  46.             {
  47.                 // Información adicional: La operación de E/S se anuló por una salida de subproceso o por una solicitud de aplicación.
  48.                 return;
  49.             }
  50.  
  51.             catch(Exception)
  52.             {
  53.                 return;
  54.             }
  55.  
  56.             // Invocar o llamar al proceso de tramas.
  57.             Invoke(new EventHandler(Actualizar));
  58.         }
  59.  
  60.  
  61.         // Como variables de clase
  62.         private string[] Separador = new string[] { ",", "\r", "\n", "/n" };
  63.         private List<string> Leo_Dato = new List<string>();
  64.  
  65.         // Procesar los datos recibidos en el bufer y extraer tramas completas.
  66.         private void Actualizar(object sender, EventArgs e)
  67.         {
  68.             Recibidos = serialPort1.ReadLine();
  69.  
  70.             double Voltaje = 0;
  71.             double Porcentaje = 0;
  72.  
  73.             // En el evento
  74.             Leo_Dato.Clear();
  75.             Leo_Dato.AddRange(Recibidos.Split(Separador, StringSplitOptions.RemoveEmptyEntries));
  76.  
  77.             //            Se produjo una excepción de tipo 'System.ArgumentOutOfRangeException' en mscorlib.dll pero no se controló en el código del usuario
  78.  
  79.  
  80.             try
  81.             {
  82.                 label_Lectura_Potenciometro.Text = Leo_Dato[0].ToString();
  83.             }
  84.  
  85.             catch (ArgumentOutOfRangeException)
  86.             {
  87.                 //Información adicional: El índice estaba fuera del intervalo. Debe ser un valor no negativo e inferior al tamaño de la colección.
  88.             }
  89.  
  90.  
  91.             progressBar1.Value = Convert.ToInt32(Leo_Dato[0].ToString());
  92.             double Dato_Voltaje = Convert.ToDouble(Leo_Dato[0]);
  93.             double Dato_Porcentaje = Convert.ToDouble(Leo_Dato[0]);
  94.  
  95.             Voltaje = Dato_Voltaje * (5.00 / 1023.00);
  96.             Porcentaje = Dato_Porcentaje * (100.00 / 1023.00);
  97.  
  98.             label_Voltio.Text = Voltaje.ToString("N2") + " V."; // N2 tiene dos decimales.
  99.             label_Portentaje.Text = Porcentaje.ToString("N2") + " %";
  100.         }
  101.  
  102.         private void Form1_FormClosing(object sender, FormClosingEventArgs e)
  103.         {
  104.  
  105.             timer1.Stop();
  106.  
  107.             if (serialPort1.IsOpen) // ¿El puerto está abierto?
  108.             {
  109.                 serialPort1.Close(); // Puerto cerrado.
  110.             }
  111.         }
  112.     }
  113. }

Seguiré con el tema de los hilos, pero cuesta entender como programarlo.

Saludos.
__________________
Meta Shell, VERSIÓN 1.2.2
Descargar
  #12 (permalink)  
Antiguo 02/05/2016, 02:50
Avatar de Malenko
Moderador
 
Fecha de Ingreso: enero-2008
Mensajes: 5.323
Antigüedad: 16 años, 3 meses
Puntos: 606
Respuesta: Se me cuelga Windows Form

Perder información por leer menos no es ninguna mejora respecto a la solución anterior. Estas leyendo solo un 10% de la información que se envía!!!

Además, como te comenté anteriormente no puedes realizar una tarea bloqueante (leer del puerto serie) y refrescar la UI en el mismo thread y es justo lo que estás haciendo en el "Actualizar".

Que utilidad tiene el try/catch del método serialPort1_DataReceived?

El try/catch del método "Actualizar" es muy fácil de evitar y aumentarías el rendimiento de tu aplicación.

Por último, porque llamas de la misma forma a la misma cosa?

Código:
double Dato_Voltaje = Convert.ToDouble(Leo_Dato[0]);
double Dato_Porcentaje = Convert.ToDouble(Leo_Dato[0]);
__________________
Aviso: No se resuelven dudas por MP!

Etiquetas: cuelga, form, visual, windows
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 07:19.