Autor
|
Tema: Barra de progreso no termina (Leído 8,030 veces)
|
Lekim
Desconectado
Mensajes: 268
|
Hola La duda que tengo es sobre el control ProgressBar y es que no termina la barra. Este código, cuando el valor de la barra llega a 100 o al máximo de la misma debe cerrarse la aplicación. Sin embargo se cierra antes que la barra llegue a 100 o al máximo establecido. Usando exactamente un código equivalente en VB6, esto no pasa. ¿Por qué ocurre? Public Class Form1 Private Time1 As New Timer() Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Call InitializeMyTimer() End Sub Private Sub InitializeMyTimer() Time1.Interval = 20 AddHandler Time1.Tick, AddressOf IncreaseProgressBar Time1.Start() End Sub Private Sub IncreaseProgressBar(ByVal sender As Object, ByVal e As EventArgs) ProgressBar1.Increment(1) If ProgressBar1.Value = ProgressBar1.Maximum Then Time1.Stop() Close() End If End Sub End Class
Gracias
|
|
« Última modificación: 14 Abril 2016, 17:44 pm por Lekim »
|
En línea
|
|
|
|
MCKSys Argentina
|
No programo mucho en .NET, pero creo que no le estas dando tiempo de refrescar. Quizas, es por eso que parece que la barra no llega al final.
Prueba de mostrar un mensaje antes de cerrar el form (u otra cosa que permita refrescar la barra, antes de cerrar).
Saludos!
|
|
|
En línea
|
MCKSys Argentina "Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."
|
|
|
Lekim
Desconectado
Mensajes: 268
|
No programo mucho en .NET, pero creo que no le estas dando tiempo de refrescar. Quizas, es por eso que parece que la barra no llega al final.
Prueba de mostrar un mensaje antes de cerrar el form (u otra cosa que permita refrescar la barra, antes de cerrar).
Saludos!
Lo de cerrar la aplicación lo he puesto como ejemplo, pero ocurre con cualquier evento. Si bajo la velocidad de progreso se nota más: Public Class Form1 Private Time1 As New Timer() Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Call InitializeMyTimer() End Sub Private Sub InitializeMyTimer() Time1.Interval = 50 AddHandler Time1.Tick, AddressOf IncreaseProgressBar Time1.Start() End Sub Private Sub IncreaseProgressBar(ByVal sender As Object, ByVal e As EventArgs) ProgressBar1.Increment(1) If ProgressBar1.Value = ProgressBar1.Maximum Then Time1.Stop() MessageBox.Show("hola") End If End Sub End Class
|
|
|
En línea
|
|
|
|
MCKSys Argentina
|
Acabo de probar tu ejemplo y el mensaje se muestra cuando la barra llega al final...
La propiedad maximum es la por default (100).
Es raro...
|
|
|
En línea
|
MCKSys Argentina "Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."
|
|
|
Lekim
Desconectado
Mensajes: 268
|
Acabo de probar tu ejemplo y el mensaje se muestra cuando la barra llega al final...
La propiedad maximum es la por default (100).
Es raro...
Gracias por probarlo. Pues si que es raro. Ejecutaré la aplicación en otra compu, haber que pasa.
Ya lo he probado. Lo he ejecutado en XP dentro de VirtualBox y funciona bien. Luego he cambiado el tema de windows a Windows Clásico y entonces si que termina. Sólo ocurre cuando se ve así:
|
|
« Última modificación: 29 Marzo 2016, 00:00 am por Lekim »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.885
|
Ten en cuenta, que una cosa son los campos (o lógica) del control, y luego, la UI. Ya te has dado cuenta por ti mismo de que la barra de progeso SÍ que llega a 100, puesto que el campo ProgressBar.Value así lo indica, pero si la UI se tuviera que actualizar/dibujar con la misma constancia, entonces la UI se volvería muy deficiente y propensa a constantes congelamientos, aparte, los efectos visuales de degradados y destellos y demás florituras, como el efecto de relleno 3D de una progressbar, requieren más trabajo/tiempo de ejecución. Viendo el código fuente online, el método Increment o PerformStep lo único que hacen es llamar a la función Win32 SendMessage para enviar el mensaje que actualiza la posición, a la cola de mensajes del control, y este mensaje se procesará cuando se desocupe el resto de mensajes que están siendo procesados constantemente por el control, suele ser algo "instantaneo", pero no tiene por que serlo, igual que el redibujado del control para mostrar esos cambios, tampoco tiene que ser instantaneo, sino cuando sucede "algo" que llame al invocador de ese evento para dispararlo. private void UpdatePos() { if (IsHandleCreated) SendMessage(NativeMethods.PBM_SETPOS, value, 0); }
En resumen, que es lo más normal del mundo, aunque para entenderlo mejor habría que conocer el código fuente de la función SendMessage para ver como funciona, y sobre todo entender a fondo como funciona la cola de mensajes para ventanas Win32, cosa que yo no se a ciencia cierta, lo que si se es que si dejas el tiempo necesario para que se procese el mensaje y se pueda actualizar la UI (unos ms), entonces puedes comprobar como si que se completa la barra de progreso hasta el final: Public NotInheritable Class Form1 : Inherits Form Friend WithEvents Timer1 As New System.Windows.Forms.Timer With {.Interval = 20} Private Sub Form1_Shown(ByVal sender As Object, ByVal e As EventArgs) _ Handles MyBase.Shown Me.ProgressBar1.Step = 1 Me.Timer1.Start() End Sub Private Sub IncreaseProgressBar(ByVal sender As Object, ByVal e As EventArgs) _ Handles Timer1.Tick Me.ProgressBar1.PerformStep() If (Me.ProgressBar1.Value = Me.ProgressBar1.Maximum) Then Me.Timer1.Stop() MsgBox("done") ' unos ms despues de saltar el msgbox verás como se completa la barra. MyBase.Close() End If End Sub End Class
Saludos.
|
|
« Última modificación: 29 Marzo 2016, 21:30 pm por Eleкtro »
|
En línea
|
|
|
|
Lekim
Desconectado
Mensajes: 268
|
Hola Elektro
Gracias por el respuesta. La cual al leerla, parce que Net lo has inventado tú ¿Como sabes esas cosas? XD
Sí comprobé que así és, por ejemplo usando sleep antes que se mostrara el mensaje, entoces la barra termina y se muestra el mensaje, pero hace un parón molesto y queda mal. También probé de usar Backgroundworker, pero ocurre exáctamente igual, que la barra termina después de mostrase el mensaje.
Necesita más tiempo para el llenado gráfico de la barra de progreso, que para los valores de la misma.
Ahora no puedo probar tu código porque estoy en XP, y aquí funcionaría bien incluso el que hice yo. Lo probaré mañana.
S2s
|
|
|
En línea
|
|
|
|
Lekim
Desconectado
Mensajes: 268
|
... En resumen, que es lo más normal del mundo, aunque para entenderlo mejor habría que conocer el código fuente de la función SendMessage para ver como funciona, y sobre todo entender a fondo como funciona la cola de mensajes para ventanas Win32, cosa que yo no se a ciencia cierta, lo que si se es que si dejas el tiempo necesario para que se procese el mensaje y se pueda actualizar la UI (unos ms), entonces puedes comprobar como si que se completa la barra de progreso hasta el final: Public NotInheritable Class Form1 : Inherits Form Friend WithEvents Timer1 As New System.Windows.Forms.Timer With {.Interval = 20} Private Sub Form1_Shown(ByVal sender As Object, ByVal e As EventArgs) _ Handles MyBase.Shown Me.ProgressBar1.Step = 1 Me.Timer1.Start() End Sub Private Sub IncreaseProgressBar(ByVal sender As Object, ByVal e As EventArgs) _ Handles Timer1.Tick Me.ProgressBar1.PerformStep() If (Me.ProgressBar1.Value = Me.ProgressBar1.Maximum) Then Me.Timer1.Stop() MsgBox("done") ' unos ms despues de saltar el msgbox verás como se completa la barra. MyBase.Close() End If End Sub End Class
Saludos. Ya he probado el código y ocurre igual, el mensaje se muestra antes que que termine la barra. Igual es cosa de mi compu o puede que del framework, porque no recuerdo que antes pasara. Como solución me fabricaré mi propia barra (que ya tengo un snippet echo para eso) y listo, ya que he comprobado que funciona usando un estilo gráfico propio y el picturebox, en lugar del progressbar. S2s
|
|
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.885
|
Ya he probado el código y ocurre igual, el mensaje se muestra antes que que termine la barra. Igual es cosa de mi compu o puede que del framework, porque no recuerdo que antes pasara. Como solución me fabricaré mi propia barra (que ya tengo un snippet echo para eso) y listo, ya que he comprobado que funciona usando un estilo gráfico propio y el picturebox, en lugar del progressbar. Sí, con el código que te mostré ocurre lo mismo, lo que te dije es que despues de mostrar el msgbox (unos ms despues), la barra se completará, por que le estás dejando tiempo suficiente para que se redibuje el control. Lo intentaré explicar de una forma más simple para que se entienda mejor: Cuando le asignas un valor del 0 al 100 a la barra de progreso, de una forma rápida como en tu código, y ves que no se completa la barra al mismo tiempo, es sencillamente por que le estás enviando actualizaciones de valor más rápido del tiempo necesario que el control o ventana necesita para procesar ese mensaje y actualizar la animación entre cada valor. Es muy posible que si administras por ti mismo el dibujado de la barra de progreso soluciones ese problema como ya has mencionado, puesto que al hacerlo (es decir, al activar el dibujado de usuario), el control se vuelve mucho más liviano, y por ende responsivo, al perder el estilo visual de Windows de la barra de progeso, es decir, la animación 3D en general, el efecto de relleno, el brillo, pseudo-translucidez parcial (no se describirlo bien), y el movimiento del efecto de "trayectoria" luminosa: ( simplemente una imagen para entender a lo que me refiero. ) Es un claro indicativo más para demostrar que el problema está en como Microsoft administra el dibujado de ese control y el tiempo de retraso que supone, puesto que es una animación, y necesita tiempo para completarse y actualizarse. EDITO:En esta respuesta comento algo relacionado sobre el tema, y dejo un snippet que tal vez te podría ser de utilidad: TL/DR:parce que Net lo has inventado tú ¿Como sabes esas cosas? XD No lo se absolutamente todo sobre los internals de Windows en relación a la API Win32/Win64, o Windows Forms, ni mucho menos, pero lo que se, lo he aprendido de forma autodidacta, a base de lectura e investigación, tragándome documentación extensa en MSDN para descubrir, aprender, y comprender, leyendo artículos interesantes en otras fuentes sobre todo tipo de temáticas relacionadas en general, redactados por programadores veteranos con décadas de experiencia en .Net, y por supuesto de la práctica, pasando por fases trial-and-error como todo el mundo, y cuando he tenido que recurrir a preguntarle a personas que saben muchísimo más que yo y me han ayudado en su momento, dignos de llamarse gurús o semi-dioses del conocimiento, como por ejemplo Hans Passant (de StackOverflow). Saludos
|
|
« Última modificación: 30 Marzo 2016, 20:50 pm por Eleкtro »
|
En línea
|
|
|
|
Lekim
Desconectado
Mensajes: 268
|
Sí, con el código que te mostré ocurre lo mismo, lo que te dije es que despues de mostrar el msgbox (unos ms despues), la barra se completará, por que le estás dejando tiempo suficiente para que se redibuje el control.
Lo intentaré explicar de una forma más simple para que se entienda mejor: Cuando le asignas un valor del 0 al 100 a la barra de progreso, de una forma rápida como en tu código, y ves que no se completa la barra al mismo tiempo, es sencillamente por que le estás enviando actualizaciones de valor más rápido del tiempo necesario que el control o ventana necesita para procesar ese mensaje y actualizar la animación entre cada valor.
Con cualquier código el, mio o el tuyo, yo si veo que acaba la barra, pero el mensaje se muestra antes que acabe. Ya supongo que el proceso matemático por así decirlo va más rápido que el gráfico. El problema está cuando se trata de dar a la oportunidad al usuario de cancelar un cierre de sesión o de windows y gráficamente parece que aún da tiempo pero en realidad no es así, además que parece que se cierra antes de tiempo. Y gracias por el snippet. s2s
He probado el Snippet. Va bien, pero vamos que pasa lo mismo. Este cierra la aplicación tras 5 segundos. Pero claro, visualmente parece que lo haga antes. Public Class Form1 Private Sub UpdateProgress(ByVal value As Integer) Me.ProgressBar1.PerformStep() My.Application.DoEvents() End Sub Private Sub Form1_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown Me.ProgressBar1.Minimum = 0 Me.ProgressBar1.Maximum = 100 Me.ProgressBar1.Step = 1 Dim Segundos As Integer = 5 For x As Integer = 0 To 100 Threading.Thread.Sleep(Segundos * 10) UpdateProgress(x) Next If ProgressBar1.Value = ProgressBar1.Maximum Then Close() End If End Sub End Class
|
|
« Última modificación: 31 Marzo 2016, 23:51 pm por Lekim »
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
ARCHIVOS .BAT + BARRA DE PROGRESO
Scripting
|
martinsan99
|
7
|
20,806
|
25 Mayo 2007, 18:43 pm
por pantocrator
|
|
|
Hacer una barra de progreso en C#
.NET (C#, VB.NET, ASP)
|
nico56
|
5
|
14,855
|
28 Diciembre 2009, 06:37 am
por nico56
|
|
|
barra de progreso
.NET (C#, VB.NET, ASP)
|
DaNuK
|
2
|
4,533
|
10 Marzo 2010, 02:05 am
por DaNuK
|
|
|
VBS barra de progreso
Programación Visual Basic
|
quico5
|
0
|
3,428
|
14 Agosto 2012, 20:41 pm
por quico5
|
|
|
barra de progreso en c++
Programación C/C++
|
d91
|
4
|
5,316
|
27 Abril 2014, 21:25 pm
por amchacon
|
|