VB.NET progressbar backgroundworker

Cuando se inicia mi aplicación, y acaba de actualizarse, estoy haciendo una actualización de la base de datos local (sqlite).

Es así: el usuario inicia mi aplicación y luego comienzo el proceso de actualización. Durante este proceso de actualización, estoy mostrando un formulario que tiene una barra de progreso continua. Este formulario se cierra cuando finaliza el proceso de actualización y el usuario puede comenzar a usar mi aplicación.

Pero la barra de progreso no se animará ya que el proceso de actualización es tan intenso.

En mi versión anterior de VB6 utilicé un ActiveX-Exe que tiene 1 formulario y muestra una barra de progreso. Este fue mi “trabajador de fondo”.

No estoy seguro si puedo usar el mismo enfoque en VB.NET.

Solo he visto ejemplos que luego hacen el trabajo en el trabajador de segundo plano, pero no he visto ningún ejemplo en el que la barra de progreso en sí sea el trabajador de segundo plano.

La actualización de la base de datos debe ser de locking, el usuario NO puede usar mi aplicación antes de que se haya realizado la actualización de la base de datos. Esto significa que solo la barra de progreso debe estar “fuera de proceso”, pero no la actualización.

¡Muchas gracias!

Primero lea esto: Uso de Application.DoEvents ()

Entonces, después de leer la respuesta anterior, nunca volverás a utilizar DoEvents, y sin los DoEvents (y / o Invalidating ProgressBar para que su evento Paint se active) la “barra de progreso no se animará ya que el proceso de actualización es tan intenso”

De ahí el comentario de Cthulhu: “Puedes hacer un diálogo con una barra de progreso, hacer que el diálogo sea modal y ejecutar tus db-cosas en un backgroundworker”. es una de las mejores maneras de avanzar.

He traducido una implementación de C # de esto que uso, debería poder incluirla directamente.

Este es el formulario de ProgressBar:

 Public Partial Class ThinkingProgressBar Inherits Form Private startTime As System.DateTime = DateTime.Now Public Sub New() InitializeComponent() End Sub Private Sub lblClose_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Me.Tag = "Cancelled" Me.Hide() End Sub Public Sub SetThinkingBar(ByVal switchedOn As Boolean) If switchedOn Then lblTime.Text = "0:00:00" startTime = DateTime.Now Timer1.Enabled = True Timer1.Start() Else Timer1.Enabled = False Timer1.Stop() End If End Sub Private Sub timer1_Tick(sender As Object, e As EventArgs) Dim diff As New TimeSpan() diff = DateTime.Now.Subtract(startTime) lblTime.Text = diff.Hours & ":" & diff.Minutes.ToString("00") & ":" & diff.Seconds.ToString("00") lblTime.Invalidate() End Sub End Class 

Arrastra / suelta un control de BackgroundWorker en el formulario, aquí están los eventos de fondo de trabajador:

 Private Sub backgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork e.Result = e.Argument 'DirectCast(e.Result, ThinkingProgressBar).SetThinkingBar(True) 'DO LONG OPERATION HERE End Sub Private Sub backgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted Dim dlg As ThinkingProgressBar = TryCast(e.Result, ThinkingProgressBar) If IsNothing(dlg) = False Then dlg.SetThinkingBar(False) dlg.Close() End If End Sub 

Y aquí está el código de llamada para cuando se inicia su aplicación y realiza la actualización:

 Dim dlg As New ThinkingProgressBar() dlg.SetThinkingBar(True) BackgroundWorker1.RunWorkerAsync(dlg) dlg.ShowDialog() If IsNothing(dlg.Tag) = False AndAlso dlg.Tag.ToString() = "Cancelled" Then Return End If 

Un par de cosas, puede evitar que el usuario lblClose_LinkClicked (es decir, lblClose_LinkClicked ) y poner en la progtwigción de protección / defensa para manejar los casos en que el usuario mata el proceso o apaga su PC durante la actualización.

Y el ProgressBar es en realidad un GIF animado, y esto se adaptará a su uso porque es muy difícil predecir el tiempo que lleva actualizar una base de datos:

enter image description here

Según sus requisitos, me parece que está buscando:

 Application.DoAction() 

Experimenté en una aplicación que había una necesidad de cargar de 2000 a 3000 elementos relacionados con los detalles de xml y el proceso implementado fue leer los elementos uno por uno, lo que interrumpe el proceso. El uso de la línea anterior en el ciclo resolvió mi problema. La interfaz de usuario no se colgó y el usuario pudo trabajar en otras formas. Esta barra de progressbar is now as background process apareció progressbar is now as background process (hasta cierto punto) para mí.

¡Espero eso ayude!

Entiendo tu deseo de hacer de la barra de progreso el hilo de fondo, pero estoy bastante seguro de que no podrás hacerlo. Como desea actualizar los componentes visuales de su aplicación, la IU debe ser el hilo principal. Es bastante fácil deshabilitar todos los controles en un formulario, incluidos los elementos del menú.

Déjame sugerir este proceso:

  1. Muestre su formulario con la barra de progreso mencionada.

  2. Si muestra otros formularios, deshabilite todos los controles secundarios que están directamente en el formulario. Dependiendo del control, es posible que tenga que pasar por sus controles secundarios para deshabilitarlos.

  3. En el código que realiza la actualización de la base de datos, actualice el valor de la barra de progreso al valor que desee. Al actualizar el valor, llame al método de actualización de la barra de progreso. Esto obligará a la barra de progreso a pintar correctamente.

  4. Una vez que se complete la actualización, oculte la barra de progreso, vuelva a habilitar todos los controles en todos los formularios que deshabilitó.

Esto le dará la apariencia de una barra de progreso que se está ejecutando en el subproceso en segundo plano mientras sigue dando a su aplicación el locking del subproceso principal como desee.

Esto no se ha probado, pero recuerdo haber hecho algo como esto para proporcionar información a un BGW. Lo cual actualizaría los contenidos del trabajador de fondo.

Primero crea una clase (es decir, ProgExample) con las siguientes variables y ponlo como un objeto global.

 Dim ProgValue as Integer; Dim ProgMax as Integer; 

Luego, alimenta la clase al trabajador de segundo plano.

 BackgroundWorker1.RunWorkerAsync(_ProgExample) 

Léelo y mantenlo adentro:

 Dim BGWProgExample as ProgExample = DirectCast(e.Argument, ProgExample), 

En segundo plano, haga algo de lo siguiente:

 BGWProgressBar.Maximum = BGWProgExample.ProgMax while BGWProgExample.ProgValue <> BGWProgExample.ProgMax BGWProgressBar.Value = BGWProgExample.ProgValue 

Entonces, cuando haya hecho algo simplemente actualice _ProgExample.ProgValue. No intente hacer esto sin una clase simplemente pasando ProgValue como argumento. Eso significaría que envía una copia de ProgValue en su estado actual y no cambiaría si actualizara ProgValue. Y si esto no sirve, pruebe Application.DoEvents y / o Application.DoAction junto con esto.

Tal vez no entiendo la pregunta, pero ¿no es realmente simple?

 For i = ProgressBar1.Minimum To ProgressBar1.Maximum ProgressBar1.Value = i ProgressBar1.Update() System.Threading.Thread.Sleep(25) Next 

La “Actualización” de Progressbar hace el truco. Su código “bloquea” (aunque no puedo ver, por qué es deseable tener “aplicación no responde”), pero la barra de progreso se actualiza d.

Por cierto: para Windows Vista / 7 (animación de la barra de progreso), puede verificar esto: ProgressBar es lento en Windows Forms

Puede generar un evento en el trabajador de segundo plano y luego actualizar la barra de progreso en el hilo de la interfaz de usuario. Puede plantear eventos en su clase y manejarlos en el formulario. Cuando se generan, puede llamar a reportprogress () en el trabajador de segundo plano.

algo más de información:

Realizar cambios de UI de larga ejecución sin bloquear el hilo principal