Autor
|
Tema: Ayuda con progresBar c#!!! (Leído 9,018 veces)
|
Hartigan
Desconectado
Mensajes: 310
|
HOla, esto no es para mi, sino para mi hermano: os pong lo que me ha puesto: Estoy intentando hacer una aplicación de escritorio que al ejecutarla, lo primero que hace es establecer conexión con la fuente de datos, que no es mas que una comprobación de que la fuente de datos existe o esta accesible para que la aplicación funcione correctamente. La interfaz que hace dixa operación es la siguiente: Lo que quiero es que el progressbar vaya sincronizado con las operaciones que se realizan, y que termine de cargarse justo cuando el acceso a la fuente de datos se a completado… El código es el siguiente: public partial class Interfaz_Conectar : Form { /* Delegados */ public delegate void Delegado_Conectar(); private delegate void Avanzar_progreso(); private delegate void Detener_progreso(); private delegate void Cerrar(); /* Eventos */ public event Delegado_Conectar Conectar; public event Delegado_Conectar noConectar; /* Proceso de segundo plano */ private BackgroundWorker bw = new BackgroundWorker (); private BackgroundWorker avanzar = new BackgroundWorker (); /* Factoria */ private Factoria_DAO factoria; /* Para finaliar el progreso de la ProgressBar */ private bool finalizar = false; private bool exito = false; public Interfaz_Conectar(Factoria_DAO _factoria) { InitializeComponent(); factoria = _factoria; } /* Evento que tiene lugar cuando se muestra el formulario por primera vez */ private void Interfaz_Conectar_Shown(object sender, EventArgs e) { bw.WorkerReportsProgress = true; bw.WorkerSupportsCancellation = true; bw .DoWork += new DoWorkEventHandler (bw_DoWork ); bw .RunWorkerCompleted += new RunWorkerCompletedEventHandler (bw_RunWorkerCompleted ); avanzar.WorkerReportsProgress = true; avanzar.WorkerSupportsCancellation = true; avanzar .DoWork += new DoWorkEventHandler (avanzar_DoWork ); //avanzar.RunWorkerCompleted += new RunWorkerCompletedEventHandler(avanzar_RunWorkerCompleted); /* Se incia la operacion en segundo plano */ avanzar.RunWorkerAsync(); /* Se inicia la operacion en segundo plano */ bw.RunWorkerAsync(); } private void bw_DoWork(object sender, DoWorkEventArgs e) { Gestion_Conectividad gconectividad = new Gestion_Conectividad (); if (gconectividad.Comprobar_conectividad(factoria)) { exito = true; finalizar = true; if (Conectar != null) Conectar(); } else { exito = false; finalizar = true; if (noConectar != null) noConectar(); } } private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (this.InvokeRequired == true) { Cerrar cerrar = new Cerrar (this.Cerrar_form); this.Invoke(cerrar); } else { this.Cerrar_form(); } } private void avanzar_DoWork(object sender, DoWorkEventArgs e) { if (this.progressBarConectar.InvokeRequired == true) { Avanzar_progreso aprogreso = new Avanzar_progreso (this.avanzar_Progreso); this.progressBarConectar.Invoke(aprogreso); } else { this.avanzar_Progreso(); } if (this.InvokeRequired == true) { Detener_progreso dprogreso = new Detener_progreso (this.detener); this.Invoke(dprogreso); } else { this.detener(); } } private void avanzar_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (this.progressBarConectar.InvokeRequired == true) { Detener_progreso dprogreso = new Detener_progreso (this.detener); this.progressBarConectar.Invoke(dprogreso); } else { this.detener(); } } private void avanzar_Progreso() { for (int i = this.progressBarConectar.Minimum; i <= this.progressBarConectar.Maximum; i++) { if (finalizar == false) { this.progressBarConectar.PerformStep(); } else { i = this.progressBarConectar.Maximum; } System.Threading.Thread.Sleep(50); } } private void detener() { if (exito) this.progressBarConectar.Value = this.progressBarConectar.Maximum; } private void Cerrar_form() { this.Close(); } }
En resumen lo que hago es crear dos subprcesos que se ejecutan en segundo plano, uno en el que se realizan las operaciones de acceso a la fuente de datos (factoria, es porque utlizo factoria abstracta junto con el patron DAO, factoria de DAO’s) y el otro subproceso es el encargado de la barra de progreso. Lo unico que hago en la barra de progereso es un Sleep del hilo y que continue cargando, y asi sucesivamente, pero obiamnete eso no v a ir sincronizado con el otro subproceso, porque no hay nada que le vaya diciendo el progeso que lleva en las operaciones de acceso a la fuente de datos… No se si me explico, de todas formas sino queda claro, explicare lo que haga falta y os asgradeczo en todo lo que me podais ayudar para conseguir hacerlo. Gracias a todos. pues eso, a ver si teneis alguna solución. Saludos
|
|
|
En línea
|
|
|
|
[D4N93R]
Wiki
Desconectado
Mensajes: 1.646
My software never has bugs. Its just features!
|
No entiendo bien, el problema que tienes es que no puedes sincronizar el hilo que va evaluando la base de datos con el ProgressBar? Bueno, con respecto al tema, no hace falta dos Hilos, uno solo es suficiente.
Luego entonces, te puede dar problemas ya que no puedes comunicarte con controles desde un subproceso, por lo que tendrías que hacer un invoke al hilo del formulario y pasarle un delegado que apunte al método que actualiza el ProgressBar.
Me gustaría también que corrigieras un poco tu nomenclatura, Te recomiendo que programes en inglés, ya que sería un solo lenguaje, se ve como raro New Cliente, es mejor New Client por ejemplo..
Bueno, espero me respondas y me digas bien cual es el problema.
Saludos!
|
|
|
En línea
|
|
|
|
Hartigan
Desconectado
Mensajes: 310
|
Exacto, el problema esque no puedo sincronizarlos, el hilo que va evaluando la base de datos y realizando la conexion con esta, con el hilo del progressbar...
Como podria hacerlo con un solo hilo?? No entiendo muy bien lo que dices...
Gracias por la respuesta
|
|
|
En línea
|
|
|
|
[D4N93R]
Wiki
Desconectado
Mensajes: 1.646
My software never has bugs. Its just features!
|
El método dowork del backgroundworker es el que va a hacer todo, no hace falta dos hilos, ni sincronizarlos, hazlo todo en el mismo método..
|
|
|
En línea
|
|
|
|
43H4FH44H45H4CH49H56H45H
Wiki
Desconectado
Mensajes: 502
|
Exacto, el problema esque no puedo sincronizarlos, el hilo que va evaluando la base de datos y realizando la conexion con esta, con el hilo del progressbar...
Como podria hacerlo con un solo hilo??
De pasada (ya que es viernes ) mira este ejemplo: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.Threading; namespace WindowsFormsApplication1 { public partial class Form1 : Form { Thread myThread; delegate void SetValueCallback(int valor); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { myThread = new Thread (new ThreadStart (listar )); myThread.Start(); } private void Form1_Load(object sender, EventArgs e) { progressBar1.Minimum = 0; } private void listar() { int i = 0; DirectoryInfo dInfo = new DirectoryInfo (@"C:\Windows\"); FileInfo[] finfo = dInfo.GetFiles("*.*", SearchOption.AllDirectories); this.SetMax(finfo.Length); foreach (FileInfo f in finfo) { this.SetValue(i += 1); System.Threading.Thread.Sleep(50); } } private void SetValue(int valor) { if (this.InvokeRequired) { SetValueCallback d = new SetValueCallback (SetValue ); this.Invoke(d, new object[] { valor }); } else { this.progressBar1.Value = valor; } } private void SetMax(int valor) { if (this.InvokeRequired) { SetValueCallback d = new SetValueCallback (SetMax ); this.Invoke(d, new object[] { valor }); } else { this.progressBar1.Maximum = valor; } } } }
Lista una carpeta, luego el número de archivos en la misma pasa a ser el valor máximo del PB, por último va recorriendo cada archivo de la carpeta y al hacerlo va cambiando el valor del PB hasta llegar al máximo. Puedes modificarlo y mejorarlo para lo que necesitas.
|
|
|
En línea
|
-R IP :0100 -A 100 2826:0100 MOV AH,09 2826:0102 MOV DX,109 2826:0105 INT 21 2826:0105 MOV AH,08 2826:0105 INT 21 2826:0107 INT 20 2826:0109 DB 'MI NICK ES CODELIVE.$' 2826:0127 -R BX :0000 -R CX :20 -N CODELIVE.COM -W
|
|
|
Hartigan
Desconectado
Mensajes: 310
|
Muchas gracias! Ahora ya se hacerlo! Solo tengo un pequeño problema, y esuqe para establecer el valor maximo del progressbar necesito cuantificar el tiempo que tarda el subproceso en acceder a la base de datos... como puedo hacerlo?? El subproceso no hace mas que esto: public override bool Comprobar_conexion(string database) { /* Exito */ bool conectado = false; /* Sentencia Sql */ String querySel = "EXEC sp_databases"; /* Conexion con la base de datos */ SqlConnection cnn = null; try { /* Conexion */ cnn = new SqlConnection (cadena_conexion ); SqlDataAdapter da = new SqlDataAdapter (querySel, cnn ); /* Se almacenan los datos obtenidos en el DataTable */ DataTable dt = new DataTable (); cnn.Open(); da.Fill(dt); cnn.Close(); /* Se busca la base de datos que queremos conectar */ for (int i = 0; i < dt.Rows.Count; i++) { if (dt.Rows[i][0].ToString() == database) conectado = true; } } catch (SqlException ex) { MessageBox.Show("ERROR al conectar con la base de datos:\n" + ex.Message, "Conexion", MessageBoxButtons.OK, MessageBoxIcon.Error); conectado = false; } finally { if (cnn != null) { if (cnn.State == ConnectionState.Open) cnn.Close(); } } return (conectado); }
|
|
|
En línea
|
|
|
|
[D4N93R]
Wiki
Desconectado
Mensajes: 1.646
My software never has bugs. Its just features!
|
cuantificar el tiempo que tarda el subproceso en acceder a la base de datos Para que haces eso? Solamente toma la conexión a la base de datos como un step más del progressbar.. Saludos!
|
|
|
En línea
|
|
|
|
43H4FH44H45H4CH49H56H45H
Wiki
Desconectado
Mensajes: 502
|
Solo tengo un pequeño problema, y esuqe para establecer el valor maximo del progressbar necesito cuantificar el tiempo que tarda el subproceso en acceder a la base de datos... como puedo hacerlo?? Podrias hacer que mientras el hilo este activo vaya subiendo el valor del PB y una vez que acabe el PB tome su valor maximo (no importa el numero maximo, solo depende cuanto aumenta el value en cada cierto tiempo). Si lo haces de ese modo podrias tener un rango de tiempo de espera para la conexion, si no logra conectarse anulas el proceso. En otro caso, podrias dividir el maximo del PB entre cada linea de tu code y tb para el for. Bueno hay mas modos, pero creo que es lo que buscas.
|
|
|
En línea
|
-R IP :0100 -A 100 2826:0100 MOV AH,09 2826:0102 MOV DX,109 2826:0105 INT 21 2826:0105 MOV AH,08 2826:0105 INT 21 2826:0107 INT 20 2826:0109 DB 'MI NICK ES CODELIVE.$' 2826:0127 -R BX :0000 -R CX :20 -N CODELIVE.COM -W
|
|
|
Hartigan
Desconectado
Mensajes: 310
|
Vale, gracias a los dos! He modificado un poco el codigo, segun lo que me habeis dixo, aunque no tengo muy claras las ideas, pero os pongo el codigo a ver si voy bien encaminado... public partial class Interfaz_Conectar : Form { /* Delegados */ public delegate void Delegado_Conectar(); private delegate void Detener_progreso(); private delegate void Cerrar(); /* Eventos */ public event Delegado_Conectar Conectar; public event Delegado_Conectar noConectar; /* Proceso de segundo plano */ private BackgroundWorker bw = new BackgroundWorker (); /* Factoria */ private Factoria_DAO factoria; public Interfaz_Conectar(Factoria_DAO _factoria) { InitializeComponent(); this.factoria = _factoria; } /* Evento que tiene lugar cuando se muestra el formulario por primera vez */ private void Interfaz_Conectar_Shown(object sender, EventArgs e) { bw.WorkerReportsProgress = true; bw.WorkerSupportsCancellation = true; bw.WorkerReportsProgress = true; bw .DoWork += new DoWorkEventHandler (bw_DoWork ); bw .RunWorkerCompleted += new RunWorkerCompletedEventHandler (bw_RunWorkerCompleted ); bw .ProgressChanged += new ProgressChangedEventHandler (bw_ProgressChanged ); if (bw.IsBusy != true) { /* Se inicia la operacion en segundo plano */ bw.RunWorkerAsync(); } } private void bw_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; int contador = this.progressBarConectar.Minimum; while (worker.CancellationPending != true) { if (worker.CancellationPending == true) { e.Cancel = true; break; } else { Gestion_Conectividad gconectividad = new Gestion_Conectividad (); if (gconectividad.Comprobar_conectividad(factoria)) { if (Conectar != null) Conectar(); } else { if (noConectar != null) noConectar(); } contador++; System.Threading.Thread.Sleep(100); worker.ReportProgress(/* ¿ que valor le paso? */ contador); } } } private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (!(e.Error == null)) { if (noConectar != null) noConectar(); } else { this.progressBarConectar.Value = this.progressBarConectar.Maximum; if (this.InvokeRequired == true) { Cerrar cerrar = new Cerrar (this.Cerrar_form); this.Invoke(cerrar); } else { this.Cerrar_form(); } } } private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) { progressBarConectar.Value = e.ProgressPercentage; } private void Cerrar_form() { this.Close(); } }
Primer problema: Gestion_Conectividad gconectividad = new Gestion_Conectividad (); if (gconectividad.Comprobar_conectividad(factoria)) { if (Conectar != null) Conectar(); } else { if (noConectar != null) noConectar(); }
No se como meter este trozo de codigo que es el que inicia las operaciones hacia la base de datos, y de manera paralela un bucle que haga un Sleep y el incremento del valor del PB... Porque lo que yo tengo puesto ahora, es un bucle "estupido" que realiza un monton de veces la misma operacion a la base de datos xD Gracias a los dos por las respuestas..
|
|
|
En línea
|
|
|
|
Hartigan
Desconectado
Mensajes: 310
|
Bueno, al final he decidido que es mejor poner un ProgressBar con el Style Marquee, pues creo que es mas logico... Pero con el nuevo codigo sigo teniendo problemas... y es que no se muestra el progreso, es decir, no se carga la barrita, no He leido webs y mas webs, codigos y codigos... y en todas partes pone que lo unico que hay que acer para hacer un que empiece el Progress Bar es establecer el ProgressBarSytle a marquee, y el MarqueeAnimatinSpeed al valor que se quiera, ademas de tener Application.EnableVisualStyles()... El codigo: -- Con un solo subproceso en segundo plano: public partial class Interfaz_Conectar : Form { /* Delegados */ public delegate void Delegado_Conectar(); private delegate void Cerrar(); private delegate void Animar_ProgressBar(); /* Eventos */ public event Delegado_Conectar Conectar; public event Delegado_Conectar noConectar; /* Proceso de segundo plano */ private BackgroundWorker bw = new BackgroundWorker (); /* Factoria */ private Factoria_DAO factoria; public Interfaz_Conectar(Factoria_DAO _factoria) { InitializeComponent(); this.factoria = _factoria; } /* Evento que tiene lugar cuando se muestra el formulario por primera vez */ private void Interfaz_Conectar_Shown(object sender, EventArgs e) { bw.WorkerReportsProgress = true; bw.WorkerSupportsCancellation = true; bw .DoWork += new DoWorkEventHandler (bw_DoWork ); bw .RunWorkerCompleted += new RunWorkerCompletedEventHandler (bw_RunWorkerCompleted ); if (bw.IsBusy != true) { /* Se inicia la operacion en segundo plano */ bw.RunWorkerAsync(); } } private void bw_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; if (worker.CancellationPending == true) { e.Cancel = true; } else { // Llamada segura desde el para animar el progressBar if (this.InvokeRequired == true) { Animar_ProgressBar animarPb = new Animar_ProgressBar (this.animarProgressBar); this.Invoke(animarPb); } else { this.animarProgressBar(); } // Operaciones que realiza el subpreceso (conexcion con al base de datos) Gestion_Conectividad gconectividad = new Gestion_Conectividad (); System.Threading.Thread.Sleep(100); if (gconectividad.Comprobar_conectividad(factoria)) { if (Conectar != null) Conectar(); } else { if (noConectar != null) noConectar(); } } } private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (!(e.Error == null)) { if (noConectar != null) noConectar(); } else { if (this.InvokeRequired == true) { Cerrar cerrar = new Cerrar (this.Cerrar_form); this.Invoke(cerrar); } else { this.Cerrar_form(); } } } private void animarProgressBar() { this.progressBarConectar.Style = ProgressBarStyle.Marquee; this.progressBarConectar.MarqueeAnimationSpeed = 100; } } private void Cerrar_form() { // Se detiene el progressBar y se cierra el form this.progressBarConectar.Style = ProgressBarStyle.Blocks; this.progressBarConectar.MarqueeAnimationSpeed = 0; this.Close(); } }
-- CON DOS SUBPROCESOS COMO SOLUCION PARA LLAMAR EN UN BUCLE A "APPLICATION.DOEVENTS()" public partial class Interfaz_Conectar : Form { /* Delegados */ public delegate void Delegado_Conectar(); private delegate void Cerrar(); private delegate void Animar_ProgressBar(); /* Eventos */ public event Delegado_Conectar Conectar; public event Delegado_Conectar noConectar; /* Proceso de segundo plano */ private BackgroundWorker bw = new BackgroundWorker (); private BackgroundWorker bwProgressBar = new BackgroundWorker (); /* Factoria */ private Factoria_DAO factoria; public Interfaz_Conectar(Factoria_DAO _factoria) { InitializeComponent(); this.factoria = _factoria; } /* Evento que tiene lugar cuando se muestra el formulario por primera vez */ private void Interfaz_Conectar_Shown(object sender, EventArgs e) { bwProgressBar.WorkerReportsProgress = true; bwProgressBar.WorkerSupportsCancellation = true; bwProgressBar .DoWork += new DoWorkEventHandler (bwProgressBar_DoWork ); bwProgressBar .RunWorkerCompleted += new RunWorkerCompletedEventHandler (bwProgressBar_RunWorkerCompleted ); bw.WorkerReportsProgress = true; bw.WorkerSupportsCancellation = true; bw .DoWork += new DoWorkEventHandler (bw_DoWork ); bw .RunWorkerCompleted += new RunWorkerCompletedEventHandler (bw_RunWorkerCompleted ); if (bwProgressBar.IsBusy != true) { bwProgressBar.RunWorkerAsync(); } if (bw.IsBusy != true) { /* Se inicia la operacion en segundo plano */ bw.RunWorkerAsync(); } } private void bwProgressBar_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; if (worker.CancellationPending) { e.Cancel = true; } else { if (this.InvokeRequired == true) { Animar_ProgressBar animarPb = new Animar_ProgressBar (this.animarProgressBar); this.Invoke(animarPb); } else { this.animarProgressBar(); } } } private void bwProgressBar_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (!(e.Error == null)) { if (noConectar != null) noConectar(); } else { this.progressBarConectar.Style = ProgressBarStyle.Blocks; this.progressBarConectar.MarqueeAnimationSpeed = 0; } } private void bw_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; if (worker.CancellationPending == true) { e.Cancel = true; } else { Gestion_Conectividad gconectividad = new Gestion_Conectividad (); System.Threading.Thread.Sleep(1000); if (gconectividad.Comprobar_conectividad(factoria)) { if (Conectar != null) Conectar(); } else { if (noConectar != null) noConectar(); } } } private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (!(e.Error == null)) { if (noConectar != null) noConectar(); } else { if (this.InvokeRequired == true) { Cerrar cerrar = new Cerrar (this.Cerrar_form); this.Invoke(cerrar); } else { this.Cerrar_form(); } } } private void animarProgressBar() { Boolean animar = true; if (animar) { this.progressBarConectar.Style = ProgressBarStyle.Marquee; this.progressBarConectar.MarqueeAnimationSpeed = 100; while (!this.bwProgressBar.CancellationPending) { Application.DoEvents(); } } } private void Cerrar_form() { this.bwProgressBar.CancelAsync(); this.Close(); } }
Ayuda plz, no consigo que funcionee de ninguna de las dos maneras ... Gracias
|
|
|
En línea
|
|
|
|
|
|