Il BackgroundWorker è a tutti gli effetti una implementazione multithread, quindi non è ben chiaro "dove" o "a cosa" sei tornato nello specifico.
Senza poter vedere il codice, è difficile diagnosticare quale possa essere l'origine del problema.![]()
Il BackgroundWorker è a tutti gli effetti una implementazione multithread, quindi non è ben chiaro "dove" o "a cosa" sei tornato nello specifico.
Senza poter vedere il codice, è difficile diagnosticare quale possa essere l'origine del problema.![]()
MARCO BREVEGLIERI
Software and Web Developer, Teacher and Consultant
Home | Blog | Delphi Podcast | Twitch | Altro...
Si intendo al multiTrhad classico
non se è corretto quello che ho fatto a livello teorico.
- Click bottone
- viene lanciato il form della progress bar
- nel load della progress bar vine lanciato il nuovo thread "sub loading"
- nella "sub loading" attraverso dei delegati lancio le sub che svolgono le varie funzini: ad sempio incremento progress bar e le funzioni che mi servono per il codice.
a livello teorico il processo che ho seguito è corretto?
codice:Public Sub ProgressBar_Load(sender As Object, e As EventArgs) Handles MyBase.Load ProgressBar1.Minimum = 0 ProgressBar1.Maximum = 10 t = New Threading.Thread(AddressOf LoadingProgressBar) t.Start() End Sub
Ultima modifica di BoBoPoP; 22-05-2019 a 12:20
Non ci sono varianti "moderne" o "classiche" del multithreading.
Spiegato a parole potrebbe anche essere corretto, ma quello che conta è l'implementazione.
Se chiami le funzioni di aggiornamento della Progress Bar e di elaborazione tutte sul thread esterno, quando sarà in esecuzione l'una si bloccherà l'altra, e viceversa. In pratica, così a prima vista, hai creato un thread esterno dove hai spostato i problemi che avevi sul primo thread principale.
E' chiaro che senza codice, come già detto, non si può dire molto.
MARCO BREVEGLIERI
Software and Web Developer, Teacher and Consultant
Home | Blog | Delphi Podcast | Twitch | Altro...
codice:Imports System.Threading Public Class Form1 Dim t As Thread Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load ProgressBar1.Minimum = 0 ProgressBar1.Maximum = 1000 t = New Threading.Thread(AddressOf LoadingProgressBar) t.Start() End Sub Private Sub LoadingProgressBar() Try Dim i As Integer Dim progress As Integer = 0 For i = 0 To 1000 Me.Invoke(up, i) Me.Invoke(updateStatus, i) Me.Invoke(msg, i) Thread.Sleep(1000) Next Me.Invoke(closeForm) Catch ex As ThreadAbortException Err.Clear() Me.Invoke(closeForm) End Try End Sub 'Delegate method to allows other thread to update value of Progress Bar Private Delegate Sub updateProgress(ByVal val As Integer) Private up As New updateProgress(AddressOf UpdateValue) 'Delegate method to allows other thread to close Private Delegate Sub closeMe() Private closeForm As New closeMe(AddressOf CloseSplash) 'Delegate method to allows other thread to update text of Label Status Private Delegate Sub setStatus(ByVal status As Integer) Private updateStatus As New setStatus(AddressOf WriteLabel) Private Delegate Sub message(ByVal i As Integer) Private msg As New message(AddressOf messaggio) 'UpdateValue method has been implemented to update value of progress Bar Private Sub UpdateValue(ByVal val As Integer) ProgressBar1.Value = val End Sub 'WriteLabel Private Sub WriteLabel(ByVal text As String) lbl.Text = text End Sub Private Sub messaggio(i As Integer) MsgBox(i) End Sub 'Close Private Sub CloseSplash() Me.Close() End Sub Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click t.Abort() End Sub End Class
Grazie a te le cose adesso sono piu chiare, questo è un estratto d'esempio.
quando parte il MSGbox il trhead si blocca quindi non è possibile adortire da tasto, invece io vorrei avere la possibilità di abortirlo ugualmente cliccando il Button1
Ultima modifica di BoBoPoP; 22-05-2019 a 14:46
Non mi è chiaro il ruolo del ciclo For che praticamente non dovrebbe esserci, visto che la ProgressBar andrebbe aggiornata in modo significativo: se le tue procedure di calcolo finiscono prima, il programma dovrà teoricamente attendere la fine del ciclo (fino a 1000), con un secondo di attesa a ogni iterazione, quindi 1000 secondi almeno per poter giungere alla fine, mentre la ProgressBar andrebbe aggiornata impostando un valore sensato, per intenderci che segnali il 90% quando ci si trova al 90% dell'intero processo.
In caso contrario, oltre a non servire, fornisce una informazione fuorviante.
Il problema principale credo sia da ricercare nel fatto che si utilizza o si fa riferimento sempre al MainForm, anche dal thread secondario, e questo non dovrebbe avvenire: è il thread principale dell'applicazione che ha la responsabilità di aggiornare l'interfaccia dell'utente, e quindi di agire sui Form, sui controlli che ne fanno parte e così via, ricevendo i messaggi corretti.
Il thread secondario deve occuparsi delle operazioni che coinvolgono calcoli o un processo lungo, ma non deve interagire con il MainForm.
Tutt'al più, è il MainForm che grazie al riferimento al thread secondario, può andarsi a leggere dei campi o delle proprietà che contengano valori significativi da mostrare, come l'operazione in corso, oppure il punto in cui si è arrivati (da mettere nella ProgressBar).
Io proverei a guardare qualsiasi demo che fa uso del BackgroundWorker per un approfondimento e nozioni importanti in merito a questa fondamentale suddivisione dei compiti.
Ciò non vuol dire che un thread secondario non possa aggiornare l'interfaccia, ma dovendolo fare in modo coordinato e non simultaneo al thread principale, la necessità di sincronizzazione introduce una complessità inutile e rallenta senza motivo il processo che gira in background nel thread secondario.
Riassumendo, bisogna rivedere la struttura del codice seguendo le indicazioni fornite e gli esempi disponibili anche in rete per questi scenari.
Ciao!![]()
MARCO BREVEGLIERI
Software and Web Developer, Teacher and Consultant
Home | Blog | Delphi Podcast | Twitch | Altro...