none
BackgroundWorker en DataGridView RRS feed

  • Pregunta

  • Hola chicos buenas noches. Acudo para que de favor me apoyen. Estoy haciendo pruebas para cargar de una consulta de una base de datos a un Grid sin que se quede congelado mi Form; ya he investigado que debo hacerlo a través de BackGroundWorker y he visto varios videos e investigado en internet. De hecho tengo un ejemplo y se ejecuta perfectamente, es decir, mientras está trabajando una iteración, se puede minimizar el form, sin embargo, he seguido los pasos pero en mi ejemplo sigue congelada la pantalla y no puedo hacer nada sobre mi form ni minimizarlo hasta que termina la iteración de una consulta a la base de datos. Espero me puedan ayudar y/o orientar chicos se los agradeceré mucho. A continuación el ejemplo que encontré en internet y que funciona a la perfección:

    namespace frmNormalThread
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void btnIniciar_Click(object sender, EventArgs e)
            {
                bgwProgreso.RunWorkerAsync();
            }
            void mostrarMensaje(string mensaje)
            {
                MessageBox.Show(mensaje);
            }
    
            private void bgwProgreso_DoWork(object sender, DoWorkEventArgs e)
            {
                for (int i = 0; i <= 1000; i++)
                {
                        System.Threading.Thread.Sleep(100);
                        bgwProgreso.ReportProgress(i);             
                }
            }
    
            private void bgwProgreso_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                lblNumero.Text = e.ProgressPercentage + "%";
                progressBar1.Value= e.ProgressPercentage;
            }
    
            private void bgwProgreso_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                
                    mostrarMensaje("El reporte se canceló por el usuario");         
            }
    
            private void btnTerminar_Click(object sender, EventArgs e)
            {
                bgwProgreso.CancelAsync();
            }
        }

    En mi ejemplo y que no se ejecuta:

    namespace bgwComercial_Productos
    {
        public partial class Form1 : Form
        {
            int elementos = Datos.elementos();

            public Form1()
            {
                InitializeComponent();
            }
            private void Form1_Load(object sender, EventArgs e)
            {
               
               
            }
            private void btnProductos_Click(object sender, EventArgs e)
            {
                bgw.RunWorkerAsync();
                dataGridView1.Rows.Clear();
                         
            }
            private void bgw_DoWork(object sender, DoWorkEventArgs e)
            {
               for (int i = 0; i <= elementos; i++)
                {
                    bgw.ReportProgress(i);
                   
                }
            }
            private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                if (e.ProgressPercentage==0)
                {
                    parametrosPB();
                }
                int porciento = 0;
                int renglon = dataGridView1.Rows.Add();
                progressBar1.Value = e.ProgressPercentage;
                porciento = Convert.ToInt32((((double)e.ProgressPercentage / (double)elementos) * 100.00));
                if (e.ProgressPercentage >= elementos)
                    progressBar1.Value = progressBar1.Maximum;
                else
                   progressBar1.Value = porciento;
                dataGridView1.Rows[e.ProgressPercentage].Cells[0].Value = e.ProgressPercentage;
                dataGridView1.Rows[e.ProgressPercentage].Cells[1].Value = "Producto";
                dataGridView1.Rows[e.ProgressPercentage].Cells[2].Value = "Clasificacion";
                //dataGridView1.DataSource = Datos.obtenerDatos(txtClasificacion.Text.Trim());
            }
            private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                MessageBox.Show("carga terminada");
            }
            private void parametrosPB()
            {
                progressBar1.Value = progressBar1.Minimum;
                progressBar1.Maximum = 100;
                progressBar1.Minimum = 0;
                progressBar1.Step = 1;
            }
        }

    Los cambios a los controles los hago desde ProgressChanged, debido a que no me permite hacer cambios en DoWork por no ser controles que hayan sido creados en ese hilo. El llenado del Grid son con datos de ejemplo. Gracias por su ayuda. Saludos cordiales

    jueves, 15 de agosto de 2019 5:15

Todas las respuestas

  • hola

    Creo que confundes conceptos, cuando estas en el DoWork el codigo ejecuta en un thread separado al thread de la UI

    Cuando corres el primer ejemplo la interrelacion entre los dos thread es minima por eso notas que la pantslla no se bloque

    Ahora bien en el segundo ejemplo la cosa cambia radicalmente los thread se interfieren constantemente cuando desde uno envias un mensaje de progreso que debe interactuar con la UI para generar el dato en el grid

    Usar el BackGroundWorker para esto que planteas no sirve no tendras ninguna mejora

    Podrias iterar el for directamente en el mismo forma poniendo la linea

    Application.DoEvents();

    para devolver el control a la UI y que no se freeze

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 15 de agosto de 2019 5:49
  • Gracias por tu respuesta Leandro. Estoy más que confundida; en la teoría y prácticamente todos los videos que he consultado se menciona que para que la pantalla no se frezee se debe usar un hilo en segundo plano (backgroundworker), especialmente en tareas que consuman mucho tiempo y evitar precisamente que la pantalla no se frezee. El DoEvents() lo he colocado en varis partes de mi código y sigue igual y como dices y aunado que soy recién iniciada en la programación no he logrado que me funcione. :(
    jueves, 15 de agosto de 2019 13:14
  • hola

    >>en tareas que consuman mucho tiempo y evitar precisamente que la pantalla no se frezee

    eso es verdad, pero lo que lanzas en un thread es el procesamiento de los datos, no sea, leer un archivo, acceder a una db, tomar estos datos y trabajarlo, esto lo haces en el DoWork

    pero luego una vez que tienes los datos la representacion en pantalla la realizas en el RunWorkerCompleted ya que estas volviendo al thread de la UI para visualizar la informacion

    No realizas un acceso intensivo de acceso a la UI desde el evento de progreso

    remerco nuevamente los controles del form estan en el thread de la aplicacion, y cuando ejecutas un backgroundworker creas un thread nuevo, si tienes que acceder de uno a otro eso se penaliza

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 15 de agosto de 2019 13:20