Principales respuestas
animar MdiParent toolStripProgressBar desde mdichild

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
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
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.
-
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
-
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
-
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
-
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
-