VB.NET progressbar backgroundworker

Quando la mia applicazione si avvia, ed è appena stata aggiornata, sto facendo un aggiornamento del database locale (sqlite).

È così: l’utente avvia la mia app e quindi avvio il processo di aggiornamento. Durante questo processo di aggiornamento sto mostrando un modulo con una barra di avanzamento continua. Questo modulo si chiude quando viene eseguito il processo di aggiornamento e l’utente può iniziare a utilizzare la mia applicazione.

Ma la barra di avanzamento non si anima poiché il processo di aggiornamento è così intenso.

Nella mia vecchia versione VB6 ho usato un ActiveX-Exe che ha 1 modulo e mostra una barra di avanzamento. Questo era il mio “lavoratore in background”.

Non sono sicuro di poter utilizzare lo stesso approccio in VB.NET.

Ho visto solo esempi che poi fanno il lavoro nel lavoratore in background, ma non ho visto alcun esempio in cui la barra di avanzamento stessa fosse l’operatore in background.

L’aggiornamento del database deve essere bloccato, l’utente NON può usare la mia applicazione prima che fosse fatto l’aggiornamento del database. Ciò significa che solo la barra di avanzamento dovrebbe essere “fuori processo”, ma non l’aggiornamento.

Grazie mille!

Prima leggi questo: Uso di Application.DoEvents ()

Quindi, dopo aver letto la risposta di cui sopra, non utilizzerai mai più DoEvents, e senza DoEvents (e / o Invalidating the ProgressBar per far scattare l’evento Paint) la “barra di avanzamento non si anima dal momento che il processo di aggiornamento è così intenso”

Da qui il commento di Cthulhu: “Puoi creare una finestra di dialogo con una barra di avanzamento, rendere quella finestra di dialogo modale ed eseguire la tua db-roba su un lavoratore in background.” è uno dei migliori modi per avanzare.

Ho tradotto una versione C # di questo che uso, dovresti essere in grado di rilasciarlo direttamente.

Questo è il modulo 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 

Trascina / Rilascia un controllo BackgroundWorker sul modulo, qui ci sono gli eventi di background worker:

 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 

Ed ecco il codice di chiamata per quando l’applicazione si avvia e fa l’aggiornamento:

 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 paio di cose, si può impedire all’utente di lblClose_LinkClicked (cioè lblClose_LinkClicked ) e mettere in programmazione protettiva / difensiva per gestire i casi in cui l’utente uccide il processo o spegne il PC durante l’aggiornamento.

E la ProgressBar è in realtà una gif animata – e questo si adatterà al tuo utilizzo perché stimare il tempo necessario per aggiornare un database è molto difficile da prevedere:

inserisci la descrizione dell'immagine qui

Dalle tue esigenze mi sembra che tu stia cercando:

 Application.DoAction() 

Ho sperimentato in un’applicazione che era necessario caricare da 2000 a 3000 elementi relativi ai dettagli da xml e il processo implementato stava leggendo gli articoli uno per uno che bloccava il processo. L’utilizzo della riga precedente nel loop ha risolto il problema. L’interfaccia utente non si ritriggers e l’utente era in grado di lavorare su altri moduli. Questo progressbar is now as background process apparso progressbar is now as background process (fino a un certo punto) per me.

Spero che sia d’aiuto!

Capisco il tuo desiderio di rendere il progressbar il thread in background, ma sono abbastanza sicuro che non sarai in grado di farlo. Poiché si desidera aggiornare i componenti visivi dell’applicazione, l’interfaccia utente deve essere il thread principale. È abbastanza facile disabilitare tutti i controlli su un modulo, comprese le voci di menu.

Lasciatemi suggerire questo processo:

  1. Mostra il tuo modulo con la barra di avanzamento menzionata.

  2. Se si mostrano altri moduli, disabilitare tutti i controlli figlio direttamente nel modulo. A seconda del controllo, potrebbe essere necessario passare attraverso i relativi controlli figlio per disabilitarli.

  3. Nel codice che esegue l’aggiornamento del database, aggiorna il valore della barra di avanzamento in base al valore che desideri. Dopo aver aggiornato il valore, chiama il metodo di aggiornamento della barra di avanzamento. Ciò costringerà la barra di avanzamento a dipingere correttamente.

  4. Una volta completato l’aggiornamento, nascondi la barra di avanzamento, ritriggers tutti i controlli su tutti i moduli distriggersti.

Questo ti darà l’aspetto di una barra di avanzamento che è in esecuzione nel thread in background mentre ancora stai dando all’applicazione il blocco del thread principale come desiderato.

Questo non è testato, ma ricordo di aver fatto qualcosa del genere per alimentare le informazioni su una BGW. Che aggiornerebbe i contenuti degli utenti in background.

Per prima cosa creare una class (es. ProgExample) con le seguenti variabili e inserirla come object globale.

 Dim ProgValue as Integer; Dim ProgMax as Integer; 

Quindi invia la class all’operatore in background.

 BackgroundWorker1.RunWorkerAsync(_ProgExample) 

Leggilo e tienilo dentro:

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

Nel lavoratore in background fai qualcosa come segue:

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

Quindi, quando hai fatto qualcosa, aggiorna _ProgExample.ProgValue. Non provare a farlo senza una class semplicemente passando ProgValue come argomento. Ciò significherebbe che si invia una copia di ProgValue nel suo stato attuale e che non cambierebbe se si aggiornasse ProgValue. E se ciò non dovesse accadere, provare Application.DoEvents e / o Application.DoAction insieme a questo.

Forse non capisco la domanda, ma non è davvero semplice?

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

L ‘”aggiornamento” di Progressbar fa il trucco. Il tuo codice “blocca” (anche se non riesco a vedere, perché è desiderabile avere “applicazione non rispondente”), ma la barra di progresso viene aggiornata d.

BTW: per Windows Vista / 7 (animazione barra di avanzamento) è ansible controllare questo: ProgressBar è lento in Windows Form

È ansible generare un evento nel worker in background e quindi aggiornare la barra di avanzamento sul thread dell’interfaccia utente. Puoi aumentare eventi nella tua class e gestirli nel modulo. Quando vengono sollevati, puoi chiamare reportprogress () sul worker in background.

qualche informazione in più:

Esecuzione di modifiche all’interfaccia utente a esecuzione prolungata senza bloccare il thread principale