Aplicaciones Windows en .NET 2005
Mostrar tiempo para ejecutar consultas SQL en ProgressBar
Mostrar tiempo para ejecutar consultas SQL en ProgressBar
Bueno muchas veces nos hemos preguntado como hacer para mostrar al usuario el estado de un proceso, en ocasiones establecemos una cantidad de tiempo ya definida para que en un ProgresBar muestre el estado de nuestro proceso, sin embargo este proceso no tiene el mismo tiempo de duracion en una y otra maquina, dando la apariencia al usuario de que nuestra aplicacion se ha "muerto". Lo que haremos a continucacion sera tratar de mostrar el tiempo aproximado en un ProgresBar de un proceso determiado. El formulario debe quedar como se muestra en la imagen A. Ademas de los controles mostrados en la imagen A, agregar tambien un control BackgroundWorker1, en la imagen B se podran ver los controles con sus respectivas propiedades que se cambian:
Imagen A. Diseño del formulario
Imagen B. Tabla de controles y propiedades
Para este ejemplo he generado un archivo txt con las lineas de codigo en SQL, el archivo se llama "archivo.txt" y esta ubicado en "C:>\", la idea es poner las sentencia sql en ese documento, en este caso no he usado saltos de linea (aunque si se quisieran usar se tendria que validar en el codigo para que no los considere, para evitar algun error posterior), aqui dejo el contenido del "archivo.txt":
Citar
create database prueba
use prueba
create table usuario(id_usuario int primary key,usuario varchar(30),telefono varchar(9),estado char(1))
insert into usuario values (1,'us1','121212','1')
insert into usuario values (2,'us2','213232','0')
insert into usuario values (3,'us3','434343','1')
insert into usuario values (4,'us4','454545','0')
insert into usuario values (5,'us5','654545','1')
insert into usuario values (6,'us6','754546','0')
insert into usuario values (7,'us7','854547','1')
insert into usuario values (8,'us8','854547','0')
insert into usuario values (9,'us9','954549','1')
use prueba
create table usuario(id_usuario int primary key,usuario varchar(30),telefono varchar(9),estado char(1))
insert into usuario values (1,'us1','121212','1')
insert into usuario values (2,'us2','213232','0')
insert into usuario values (3,'us3','434343','1')
insert into usuario values (4,'us4','454545','0')
insert into usuario values (5,'us5','654545','1')
insert into usuario values (6,'us6','754546','0')
insert into usuario values (7,'us7','854547','1')
insert into usuario values (8,'us8','854547','0')
insert into usuario values (9,'us9','954549','1')
Como se pueden dar cuenta, la sentencia para crear la tabla esta en una sola linea, es necesario que este asi, ya se explicara adelante el porque de esto. Ahora veamos el codigo:
Citar
Imports System.IO
Imports System.Collections
Imports System.Data.SqlClient
Public Class Form1
Private con As New SqlConnection("integrated security=sspi;data source=(local);initial catalog=master")
Private cmd As SqlCommand
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim RutaArchivo As New StreamReader("C:\archivo.txt")
Dim total As Integer
While Not RutaArchivo.EndOfStream
total += 1
RutaArchivo.ReadLine()
End While
Me.ProgressBar1.Minimum = 0
Me.ProgressBar1.Maximum = total
Me.BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Try
Dim CalculoTiempo As New Stopwatch
Dim RutaArchivo As New StreamReader("C:\archivo.txt")
Dim porcentaje As Integer
Dim linea As String
While Not RutaArchivo.EndOfStream
If BackgroundWorker1.CancellationPending Then
Exit While
End If
CalculoTiempo.Reset()
CalculoTiempo.Start()
linea = RutaArchivo.ReadLine()
porcentaje += 1
cmd = New SqlCommand(linea, con)
cmd.CommandType = CommandType.Text
cmd.ExecuteNonQuery()
BackgroundWorker1.ReportProgress(porcentaje)
CalculoTiempo.Stop()
Threading.Thread.Sleep(CalculoTiempo.ElapsedMilliseconds)
End While
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
ProgressBar1.Value = e.ProgressPercentage
Label1.Text = "Ejecutados " & e.ProgressPercentage & " de " & Me.ProgressBar1.Maximum
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
Label2.Text = "Proceso completado"
End Sub
Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
con.Close()
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
con.Open()
End Sub
End Class
Imports System.Collections
Imports System.Data.SqlClient
Public Class Form1
Private con As New SqlConnection("integrated security=sspi;data source=(local);initial catalog=master")
Private cmd As SqlCommand
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim RutaArchivo As New StreamReader("C:\archivo.txt")
Dim total As Integer
While Not RutaArchivo.EndOfStream
total += 1
RutaArchivo.ReadLine()
End While
Me.ProgressBar1.Minimum = 0
Me.ProgressBar1.Maximum = total
Me.BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Try
Dim CalculoTiempo As New Stopwatch
Dim RutaArchivo As New StreamReader("C:\archivo.txt")
Dim porcentaje As Integer
Dim linea As String
While Not RutaArchivo.EndOfStream
If BackgroundWorker1.CancellationPending Then
Exit While
End If
CalculoTiempo.Reset()
CalculoTiempo.Start()
linea = RutaArchivo.ReadLine()
porcentaje += 1
cmd = New SqlCommand(linea, con)
cmd.CommandType = CommandType.Text
cmd.ExecuteNonQuery()
BackgroundWorker1.ReportProgress(porcentaje)
CalculoTiempo.Stop()
Threading.Thread.Sleep(CalculoTiempo.ElapsedMilliseconds)
End While
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
ProgressBar1.Value = e.ProgressPercentage
Label1.Text = "Ejecutados " & e.ProgressPercentage & " de " & Me.ProgressBar1.Maximum
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
Label2.Text = "Proceso completado"
End Sub
Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
con.Close()
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
con.Open()
End Sub
End Class
BackgroundWorker: Nos permite ejecutar una operación en un hilo independiente y dedicado. Esto, entre otras cosas, permite que la interfaz de la aplicación no deja de responder ya que nada satura su hilo propio.
Stopwatch: Los metodos Start, Stop, Reset (Inicia, Detiene, Resetea); ElapsedMilliseconds devuelve un valor Long con los milisegundos transcurridos desde que se inicio la variable.
Explicacion: Bueno como uds se pueden dar cuenta todo se hace en el evento DoWork del control backgroundworker:
Citar
Dim CalculoTiempo As New Stopwatch
CalculoTiempo sera la variable en la cual se calculara (valga la redundancia) el tiempo que demora en ejecutarse el sqlcommand, lo iniciaremos con el metodo Start y lo daremos por terminado con el metodo Stop, para el siguiente bucle antes de volver a hacer el conteo lo resetearemos con el metodo Reset.
Citar
While Not RutaArchivo.EndOfStream
CalculoTiempo.Reset() 'Reseteamos el tiempo para la variable
CalculoTiempo.Start() 'iniciamos el valor para calcular el tiempo
linea = RutaArchivo.ReadLine() ' leemos la linea de la sentencia sql
porcentaje += 1 'aumentamos el porcentaje del progessbarr
cmd = New SqlCommand(linea, con) 'instanciamos la consulta en el sqlcommand
cmd.CommandType = CommandType.Text 'definimos el tipo de comando
cmd.ExecuteNonQuery() 'ejecutamos el comando
BackgroundWorker1.ReportProgress(porcentaje) 'enviamos el porcentaje al evento ProgressChanged del BackgroundWorker.
CalculoTiempo.Stop() 'detenemos el conteo de tiempo del proceso
Threading.Thread.Sleep(CalculoTiempo.ElapsedMilliseconds) 'pausa
End While
CalculoTiempo.Reset() 'Reseteamos el tiempo para la variable
CalculoTiempo.Start() 'iniciamos el valor para calcular el tiempo
linea = RutaArchivo.ReadLine() ' leemos la linea de la sentencia sql
porcentaje += 1 'aumentamos el porcentaje del progessbarr
cmd = New SqlCommand(linea, con) 'instanciamos la consulta en el sqlcommand
cmd.CommandType = CommandType.Text 'definimos el tipo de comando
cmd.ExecuteNonQuery() 'ejecutamos el comando
BackgroundWorker1.ReportProgress(porcentaje) 'enviamos el porcentaje al evento ProgressChanged del BackgroundWorker.
CalculoTiempo.Stop() 'detenemos el conteo de tiempo del proceso
Threading.Thread.Sleep(CalculoTiempo.ElapsedMilliseconds) 'pausa
End While
Simplemente al final le decimos que en el evento ProgressChanged modifique el label1, podran leer sobre este evento aqui.
Citar
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
ProgressBar1.Value = e.ProgressPercentage
Label1.Text = "Ejecutados " & e.ProgressPercentage & " de " & Me.ProgressBar1.Maximum
End Sub
ProgressBar1.Value = e.ProgressPercentage
Label1.Text = "Ejecutados " & e.ProgressPercentage & " de " & Me.ProgressBar1.Maximum
End Sub
Bueno hemos llegado al final de este pequeño tutorial, espero que sea de utilidad, cabe recalcar que se puede usar para lo que se necesite no solo para la ejecucion de SQL, con el tipo de dato Stopwatch se pueden hacer muchas cosas. En fin ... espero algun comentario (por supuesto como mensaje privado) y si alquien se anima a continuar o aportar algo aqui enviarme un MP. Muchos saludos a todos.
Descargar archivo de Ejemplo