none
animar MdiParent toolStripProgressBar desde mdichild RRS feed

  • Pregunta

  • hola estoy tratando de animar un toolStripProgressBar en un mdicontainer desde un form mdichild 

    el codigo de la animacion es este:

    public void AnimaProgress( Boolean estado)
            {
                if (estado)
                {
                    toolStripProgressBar1.MarqueeAnimationSpeed = 30;
                    toolStripProgressBar1.Style = ProgressBarStyle.Marquee;
                }
                else
                {
                    toolStripProgressBar1.MarqueeAnimationSpeed = 0;
                }
            }

    y desde el child lo llamo asi

    public void AnimaProgressParent(Boolean estado)
            {
                if (this.MdiParent != null)
                {
                    if (estado)
                    {
                        mdi_Menu parent = this.MdiParent as mdi_Menu;
                        parent.AnimaProgress(true);
    
                    }
                    else
                    {
                        mdi_Menu parent = this.MdiParent as mdi_Menu;
                        parent.AnimaProgress(false);
                        
                    }
                }
            }

    el toolStripProgressBar  es publico tanto el statusStrip

    pero al momento de ejecutarlo me arroja el siguiente error 

    Operación no válida a través de subprocesos: Se tuvo acceso al control '' desde un subproceso distinto a aquel en que lo creó.

    estoy trabajando con Visual Studio 2010 y C#

    gracias

    martes, 27 de octubre de 2015 14:34

Respuestas

  • No. Más o menos.

    En el DoWork, dejas la línea nuevo = ds.Kardex(...

    Eso está bién en el DoWork, la pones luego del llamado a ReportProgress(), que es quien echa a andar la marquesina.

    Lo que también falta, es poner a true la propiedad  WorkerReportProgress, salvo que lo hayas hecho desde la caja de propiedades.

    private void btnReporte_Click(object sender, EventArgs e)
    {
    	nuevo = new DataTable();
    	if (backgroundWorker1.IsBusy)
    	{
    	}
    	else
    	{
    		backgroundWorker1.WorkerReportsProgress = true;
    		backgroundWorker1.RunWorkerAsync();
    	}
    }
    
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
    	backgroundWorker1.ReportProgress(0);
    	nuevo = ds.kardex(dtpFecha1.Value, dtpFecha2.Value, pro.CodProducto, frmLogin.iCodAlmacen).Tables[0]; //aqui hago la consulta que demora mucho 
    }
    
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
    	AnimaProgressParent(true);
    }
    
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
    	AnimaProgressParent(false);
    	rpt1.SetDataSource(nuevo);
    	frm.crvKardex.ReportSource = rpt1;
    	frm.Show();
    }


    • Editado AlterEgo 22 martes, 27 de octubre de 2015 21:18
    • Marcado como respuesta jvidal26 martes, 27 de octubre de 2015 23:53
    martes, 27 de octubre de 2015 21:11

Todas las respuestas

  • Ese error no tiene nada que ver con el hecho de que estés accediendo al mdiparent desde el mdichild. Se produce cuando accedes a la interfaz de pantalla (sea parent o child) desde un hilo distinto del que la creó. Mi sospecha es que has debido de llamar a tu método AnimaProgressParent desde otro hilo, bien sea porque has creado un Thread o porque has usado un Timer distinto del System.Windows.Forms.Timer.

    Si efectivamente ese es el problema, se resuelve interponiendo una llamada a Control.Invoke para que se transporte la ejecución al hilo principal. Si nos pones cómo estás llamando a AnimaProgressParent, te podemos indicar lo que hay que cambiar para que pase a través de Invoke.

    martes, 27 de octubre de 2015 18:51
  • obvie esa parte pensando que no tenia que ver pero creo que si 

    estoy trayendo un datatable de una consulta que demora mucho y para que no bloquea la aplicacion utilizo un BackGroundWorker

    aqui la llamo 

    CRKardex rpt1 = new CRKardex();
            frmRptKardex frm = new frmRptKardex();
            DataTable nuevo = new DataTable();
            private void btnReporte_Click(object sender, EventArgs e)
            {
                nuevo = new DataTable();
                if (backgroundWorker1.IsBusy)
                {
                }
                else
                {
                    backgroundWorker1.RunWorkerAsync();
                }
    
    
            }

    el doWork

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                try
                {
    
                    AnimaProgressParent(true);  //aqui llamo al metodo
                    nuevo = ds.kardex(dtpFecha1.Value, dtpFecha2.Value, pro.CodProducto, frmLogin.iCodAlmacen).Tables[0]; //aqui hago la consulta que demora mucho 
                }
                catch (Exception ex)
                {
                    e.Result = ex;
                }
            }

    el metodo

    public void AnimaProgressParent(Boolean estado)
            {
                if (this.MdiParent != null)
                {
                    if (estado)
                    {
                        mdi_Menu parent = this.MdiParent as mdi_Menu;
                        parent.AnimaProgress(true);
                    }
                    else
                    {
                        mdi_Menu parent = this.MdiParent as mdi_Menu;
                        parent.AnimaProgress(false);
                    }
                }
            }

    y cuando acaba

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                AnimaProgressParent(false);
                rpt1.SetDataSource(nuevo);
                frm.crvKardex.ReportSource = rpt1;
                frm.Show();
            }


    Alexis Vidal .NET Programmer

    martes, 27 de octubre de 2015 19:14
  • En la caja de propiedades del componente BGW, le das doble clic al evento ProgressChanged, y en el método creado por el editor, llamas a tu función AnimateProgressParent(true). Exáctamente del mismo modo que lo haces  en el método creado para atender el evento RunWorkerCompleted. En ambos casos es seguro llamar a la función, porque estos métodos corren en el mismo hilo. Cosa que el método que atiende al DoWork, no hace.

    En el DoWork, en vez de llamar a esta función, generas el evento llamando a backgroundWorker1.ReportProgress(0);

    Finalmente, en el clic, antes del run-worker-async, habilitas la generación del reporte.

    backgroundWorker1.WorkerReportsProgress = true;
    backgroundWorker1.RunWorkerAsync();
    Yo prefiero que la marquesina no sea visible, en lugar poner su speed a cero. Pero eso es cuestión de gustos.



    • Editado AlterEgo 22 martes, 27 de octubre de 2015 20:15
    martes, 27 de octubre de 2015 20:10
  • gracias por la respuesta , no se si te entendí pero creo que quedaría así? 

    private void btnReporte_Click(object sender, EventArgs e)
            {
                nuevo = new DataTable();
                nuevo = ds.kardex(dtpFecha1.Value, dtpFecha2.Value, pro.CodProducto, frmLogin.iCodAlmacen).Tables[0];
                if (backgroundWorker1.IsBusy)
                {
                }
                else
                {
                    backgroundWorker1.RunWorkerAsync();
                }
    
    
            }
    
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                backgroundWorker1.ReportProgress(0);
            }
    
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                AnimaProgressParent(true);
            }
    
            private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                AnimaProgressParent(false);
                rpt1.SetDataSource(nuevo);
                frm.crvKardex.ReportSource = rpt1;
                frm.Show();
            }

    el problema es que se bloque la aplicación porque esta consulta puede demorar hasta 3 minutos, y por eso opte por ponerla en el DoWork

    nuevo = ds.kardex(dtpFecha1.Value, dtpFecha2.Value, pro.CodProducto, frmLogin.iCodAlmacen).Tables[0];

    Alexis Vidal .NET Programmer

    martes, 27 de octubre de 2015 20:39
  • No. Más o menos.

    En el DoWork, dejas la línea nuevo = ds.Kardex(...

    Eso está bién en el DoWork, la pones luego del llamado a ReportProgress(), que es quien echa a andar la marquesina.

    Lo que también falta, es poner a true la propiedad  WorkerReportProgress, salvo que lo hayas hecho desde la caja de propiedades.

    private void btnReporte_Click(object sender, EventArgs e)
    {
    	nuevo = new DataTable();
    	if (backgroundWorker1.IsBusy)
    	{
    	}
    	else
    	{
    		backgroundWorker1.WorkerReportsProgress = true;
    		backgroundWorker1.RunWorkerAsync();
    	}
    }
    
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
    	backgroundWorker1.ReportProgress(0);
    	nuevo = ds.kardex(dtpFecha1.Value, dtpFecha2.Value, pro.CodProducto, frmLogin.iCodAlmacen).Tables[0]; //aqui hago la consulta que demora mucho 
    }
    
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
    	AnimaProgressParent(true);
    }
    
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
    	AnimaProgressParent(false);
    	rpt1.SetDataSource(nuevo);
    	frm.crvKardex.ReportSource = rpt1;
    	frm.Show();
    }


    • Editado AlterEgo 22 martes, 27 de octubre de 2015 21:18
    • Marcado como respuesta jvidal26 martes, 27 de octubre de 2015 23:53
    martes, 27 de octubre de 2015 21:11
  • muchas gracias por la ayuda lo pude solucionar

    Alexis Vidal .NET Programmer

    martes, 27 de octubre de 2015 23:54