Aggiornare la progressbar da un backgroundworker, come?

lunedì 22 settembre 2008 - 16.10

lukepet Profilo | Junior Member

Ho questo problema...

ho una form in cui sono definite queste righe di codice:

Private Sub DownloadAggiornamento()
Me.TextInfo.Text = "Download aggiornamento in corso..."
Me.ProgressBar1.Minimum = 0
Me.btnInstalla.Enabled = False

Me.bkw_Download = New System.ComponentModel.BackgroundWorker
Me.bkw_Download.WorkerSupportsCancellation = True
Me.bkw_Download.RunWorkerAsync() 'Esecuzione del task in un thread secondario
While bkw_Download.IsBusy
Application.DoEvents()
End While
End Sub

Private Sub bkw_Download_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bkw_Download.DoWork
FTPTransf.DownloadUpdate(ftpdir, "C:\temp", file)
End Sub

Private Sub bkw_Download_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bkw_Download.RunWorkerCompleted
Me.btnInstalla.Enabled = True
End Sub

la funzione DownloadUpdate è definita in una classe separata ed realizzata in questo modo:

Public Sub DownloadUpdate(ByVal Path As String, ByVal LocalPath As String, ByVal Name As String)

Dim _fileName As String = LocalPath + "\" + Name

Dim _File As FileInfo = New FileInfo(_fileName)
Dim _FileStream As FileStream
Dim filesize As Integer

_FtpRequest = CType(WebRequest.Create(Path + Name), FtpWebRequest)
_FtpRequest.Credentials = New NetworkCredential(_UserName, _Password)

'Leggo la grandezza del file
Dim _FtpRequestSize As FtpWebRequest = CType(WebRequest.Create(Path + Name), FtpWebRequest)
_FtpRequestSize.Credentials = New NetworkCredential(_UserName, _Password)
_FtpRequestSize.Method = WebRequestMethods.Ftp.GetFileSize
Dim response As FtpWebResponse = _FtpRequestSize.GetResponse
filesize = response.ContentLength

'Eseguo il download
_FtpRequest.Method = WebRequestMethods.Ftp.DownloadFile
_FtpRequest.EnableSsl = _UseSSL
_FileStream = New FileStream(_File.FullName, FileMode.Create, FileAccess.Write)
_FtpResponse = CType(_FtpRequest.GetResponse(), FtpWebResponse)

Dim _ResponseStream As Stream = _FtpResponse.GetResponseStream()
Dim buffer(1024) As Byte
Dim bytesRead As Integer = _ResponseStream.Read(buffer, 0, 1024)

FormUpd.ProgressBar1.Minimum = 0
FormUpd.ProgressBar1.Maximum = filesize
While (bytesRead <> 0)
_FileStream.Write(buffer, 0, bytesRead)
bytesRead = _ResponseStream.Read(buffer, 0, 1024)
FormUpd.ProgressBar1.Value = _FileStream.Position
End While

_FileStream.Close()
_ResponseStream.Close()

End Sub

il mio problema è che usando il BackgroundWorker la progressabar non mi viene aggiornata in tempo reale. Come devo fare per aggiornare i controlli della winform da processo in background? Sapete aiutarmi?

Grazie per ogni informazione.

rossimarko Profilo | Guru

Ciao,

occhio che hai sbagliato stanza, questa è dedicata ad ASP.NET

Comunque per gestire una progress puoi usare il metodo ReportProgress (http://msdn.microsoft.com/it-it/library/system.componentmodel.backgroundworker.reportprogress.aspx) all'interno dell'evento doWork. Questo scatena l'evento ProgressChanged (http://msdn.microsoft.com/it-it/library/system.componentmodel.backgroundworker.progresschanged.aspx) all'interno del quale puoi effettuare l'aggiornamento della tua progress
-----------------------------------------
Rossi Marco
http://blogs.dotnethell.it/rossimarko

lukepet Profilo | Junior Member

oh cavolo scusa...non ci avevo fatto caso.

Ho provato con il reportprogress ma ho qualche difficoltà nel far leggere il value della progress bar dalla funzione che gestisce il download.

rossimarko Profilo | Guru

In che senso hai qualche difficoltà?

Qui se ti serve trovi un esempio che fa uso anche del reportProgress: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
-----------------------------------------
Rossi Marco
http://blogs.dotnethell.it/rossimarko

lukepet Profilo | Junior Member

Ancora non riesco a farlo funzionare...

dunque nella classe FTP.vb ho inserito il seguente codice:

highestPercentageReached = 0
While (bytesRead <> 0)
_FileStream.Write(buffer, 0, bytesRead)
bytesRead = _ResponseStream.Read(buffer, 0, 1024)
Dim percentComplete As Integer = (CSng(_FileStream.Position) / CSng(filesize)) * 100
If percentComplete > highestPercentageReached Then
highestPercentageReached = percentComplete
FormUpd.bkw_Download.ReportProgress(percentComplete)
End If
End While

quando il programma esegue l'istruzione "FormUpd.bkw_Download.ReportProgress(percentComplete)" dà l'errore "Riferimento a un oggetto non impostato su un'istanza di oggetto".

nella classe FormUpd ho il seguente codice:

Public Class FormUpd
Friend WithEvents bkw_Download As System.ComponentModel.BackgroundWorker
.
.
Private Sub DownloadAggiornamenti()
Me.ProgressBar1.Minimum = 0
Me.bkw_Download = New System.ComponentModel.BackgroundWorker
Me.bkw_Download.WorkerSupportsCancellation = True
For i As Integer = 0 To files.Count - 1
filecorrente = files(i).ToString
Me.bkw_Download.RunWorkerAsync() 'Esecuzione del task in un thread secondario
While bkw_Download.IsBusy
Application.DoEvents()
End While
Next
End Sub

Private Sub bkw_Download_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bkw_Download.DoWork
FTPTransf.DownloadUpdate(ftpdir, dirLocaleTemp, filecorrente)
End Sub

' This event handler updates the progress bar.
Private Sub bkw_Download_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) _
Handles bkw_Download.ProgressChanged
Me.ProgressBar1.Value = e.ProgressPercentage
End Sub

Non riesco a capire cosa c'è che non va.

rossimarko Profilo | Guru

Prova a fare come nell'esempio che ti ho postato in precedenza. Il riferimento al backgroud worker viene passato come parametro alla funzione, mentre nel tuo caso tu punti direttamente alla form. Questo è il pezzo di codice all'interno dell'esempio:

' This event handler is where the actual work is done. Private Sub backgroundWorker1_DoWork( _ ByVal sender As Object, _ ByVal e As DoWorkEventArgs) _ Handles backgroundWorker1.DoWork ' Get the BackgroundWorker object that raised this event. Dim worker As BackgroundWorker = _ CType(sender, BackgroundWorker) ' Assign the result of the computation ' to the Result property of the DoWorkEventArgs ' object. This is will be available to the ' RunWorkerCompleted eventhandler. e.Result = ComputeFibonacci(e.Argument, worker, e) End Sub 'backgroundWorker1_DoWork
-----------------------------------------
Rossi Marco
http://blogs.dotnethell.it/rossimarko

lukepet Profilo | Junior Member

Hai ragione...ho risolto.

Ho passato il worker tra i parametri della funzione

Public Sub DownloadUpdate(ByVal Path As String, ByVal LocalPath As String, ByVal Name As String, ByVal worker As BackgroundWorker, ByVal e As DoWorkEventArgs)

eseguendo all'interno l'istruzione: worker.ReportProgress(percentComplete)

nella classe FormUpd invece ho modificato così:

Private Sub bkw_Download_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bkw_Download.DoWork
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
FTPTransf.DownloadUpdate(ftpdir, dirLocaleTemp, filecorrente, worker, e)
End Sub

Grazie per l'aiuto.
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5