2013-07-31 134 views
1

所以,我終於得到了這幾乎的工作,但現在每天我幾次測試過程中的形式和進度凍結。我也確信有這樣做的更有效的方法,所以任何建設性的批評將不勝感激。BackgroundWorker的進度凍結

這是一個程序,允許用戶點擊一個按鈕,下載並安裝一個應用程序,然後按下一個按鈕,下載並安裝不同的應用程序的一個頁面編碼:

Imports System.Net.WebRequestMethods 
Public Class Software 

'Open link in external browser 
Public Sub HandleRequestNavigate(ByVal sender As Object, ByVal e As RequestNavigateEventArgs) 
    Process.Start(New ProcessStartInfo(e.Uri.AbsoluteUri)) 
    e.Handled = True 
End Sub 

'Declarations 
Shared progressamc As New Progress 
Shared progresscti As New ProgressCTI 
WithEvents startcti As New Process 
WithEvents startamc As New Process 
WithEvents startsfstb As New Process 
WithEvents amcworker As New ComponentModel.BackgroundWorker 
WithEvents ctiworker As New ComponentModel.BackgroundWorker 
Dim ProgressBarAMC As Object = Progress.ProgressBar1 
Dim blprgrsAMC As Object = Progress.blprgrs 
Dim ProgressBarCTI As Object = progresscti.ProgressBar1 
Dim blprgrsCTI As Object = progresscti.blprgrs 


'FTP Values 
Const host As String = "ftp://10.167.16.80/" 
Const username As String = "anonymous" 
Const password As String = "" 
'AMC File Put/Get 
Const localfileamc As String = "C:\AMC.exe" 
Const Remotefileamc As String = "Bin/AMC.exe" 
'CTI File Put/Get 
Const localfilecti As String = "C:\CTI.exe" 
Const Remotefilecti As String = "Bin/CTI.exe" 

'On Init 
Public Sub New() 
    InitializeComponent() 
    amcworker.WorkerReportsProgress = True 
    amcworker.WorkerSupportsCancellation = True 
    ctiworker.WorkerReportsProgress = True 
    ctiworker.WorkerSupportsCancellation = True 
End Sub 

'Install AMC Button 
Private Sub ButtonAMC(sender As Object, e As RoutedEventArgs) 
    Dim butt1 As Button = DirectCast(sender, Button) 
    butt1.IsEnabled = False 
    Dispatcher.BeginInvoke(New Action(AddressOf progressamc_Show)) 
    AddHandler Progress.Cancel_Click, AddressOf myProcessamc_Exited 
    amcworker.RunWorkerAsync() 
End Sub 

'Open Dialog 
Private Sub progressamc_Show() 
    Try 
     progressamc.ShowDialog() 
    Catch ex As Exception 
     MessageBox.Show("An error has occurred during the process:" & vbCrLf & vbCrLf & ex.Message & vbCrLf & vbCrLf & "Please close the application and try again." _ 
       & vbCrLf & "If you continue to encounter this error please Email") 
    End Try 
End Sub 

'FTP - Download 
Private Sub ftpseshamc_DoWork(ByVal sender As System.Object, ByVal e As ComponentModel.DoWorkEventArgs) Handles amcworker.DoWork 
    Dim URI As String = host & Remotefileamc 
    Dim FTP As System.Net.FtpWebRequest = CType(System.Net.FtpWebRequest.Create(URI), System.Net.FtpWebRequest) 
    'Set the credentials 
    FTP.Credentials = New System.Net.NetworkCredential(username, password) 
    'FTP Options 
    FTP.KeepAlive = False 
    FTP.UseBinary = True 
    'Define the action as Download 
    FTP.Method = System.Net.WebRequestMethods.Ftp.DownloadFile 
    'Get the response to the Ftp request and the associated stream 
    Try 
     Dim response As System.Net.FtpWebResponse = CType(FTP.GetResponse, System.Net.FtpWebResponse) 
     Dim Length As Long = response.ContentLength 
     Dim StopWatch As New Stopwatch 
     Dim CurrentSpeed As Double = Nothing 
     Using responseStream As IO.Stream = response.GetResponseStream 
      'loop to read & write to file 
      Using fs As New IO.FileStream(localfileamc, IO.FileMode.Create) 
       Dim buffer(2047) As Byte 
       Dim read As Integer = 0 
       Dim count As Integer 
       Do 
        If amcworker.CancellationPending = True Then 
         e.Cancel = True 
         Return 
        End If 
        StopWatch.Start() 
        amcworker.ReportProgress(CShort(count/Length * 100 + 0.5)) 
        read = responseStream.Read(buffer, 0, buffer.Length) 
        fs.Write(buffer, 0, read) 
        count += read 
       Loop Until read = 0 
       StopWatch.Stop() 
       responseStream.Close() 
       fs.Flush() 
       fs.Close() 
      End Using 
      responseStream.Close() 
     End Using 
     response.Close() 
    Catch ex As Exception 
     MessageBox.Show("An error has occurred during the process:" & vbCrLf & vbCrLf & ex.Message & vbCrLf & vbCrLf & "Please close the application and try again." _ 
         & vbCrLf & "If you continue to encounter this error please Email") 
     myProcessamc_Exited() 
    End Try 
    Installamc() 
End Sub 

'Starts the installation 
Sub Installamc() 
    startamc.StartInfo.FileName = "C:\AMC.exe" 
    startamc.EnableRaisingEvents = True 
    Try 
     startamc.Start() 
    Catch ex As Exception 
     MsgBox(ex.Message) 
    End Try 
    Dispatcher.Invoke(New Action(AddressOf Progressamc_Hide)) 
End Sub 
'Hide Dialog during install 
Private Sub Progressamc_Hide() 
    progressamc.Hide() 
End Sub 

'Report progress 
Private Sub amcworker_ProgressChanged(ByVal sender As System.Object, ByVal e As ComponentModel.ProgressChangedEventArgs) Handles amcworker.ProgressChanged 
    ProgressBarAMC.value = e.ProgressPercentage 
    blprgrsAMC.Content = "Downloading: " & e.ProgressPercentage & "%" 
End Sub 

End Class 

再次, 任何幫助將不勝感激。

編輯:我做了以下修改的代碼,但我不能完全肯定它做什麼,我認爲它在做什麼。基本上我的意圖是讓ReportProgress只在每讀取2047個字節時運行一次。

'Get the response to the Ftp request and the associated stream 
    Try 
     Dim response As System.Net.FtpWebResponse = CType(FTP.GetResponse, System.Net.FtpWebResponse) 
     Dim Length As Long = response.ContentLength 
     Dim StopWatch As New Stopwatch 
     Dim CurrentSpeed As Double = Nothing 
     Using responseStream As IO.Stream = response.GetResponseStream 
      'loop to read & write to file 
      Using fs As New IO.FileStream(localfileamc, IO.FileMode.Create) 
       Dim buffer(2047) As Byte 
       Dim read As Integer = 0 
       Dim count As Integer 
       Dim chunk As Integer = Int(2047/Length) 
       Dim cycle As Integer = chunk = count 
       Do 
        If amcworker.CancellationPending = True Then 
         e.Cancel = True 
         Return 
        End If 
        StopWatch.Start() 
        If cycle = True Then 
         amcworker.ReportProgress(CShort(count/Length * 100 + 0.5)) 
        Else 
         End 
        End If 
        read = responseStream.Read(buffer, 0, buffer.Length) 
        fs.Write(buffer, 0, read) 
        count += read 
       Loop Until read = 0 
       StopWatch.Stop() 
       responseStream.Close() 
       fs.Flush() 
       fs.Close() 
      End Using 
      responseStream.Close() 
     End Using 
     response.Close() 
    Catch ex As Exception 
     MessageBox.Show("An error has occurred during the process:" & vbCrLf & vbCrLf & ex.Message & vbCrLf & vbCrLf & "Please close the application and try again." _ 
         & vbCrLf & "If you continue to encounter this error please Email") 
     myProcessamc_Exited() 
    End Try 
+2

這是太多的代碼。你能把它縮小到你的問題的一個最小的例子嗎? – Blorgbeard

+0

縮短了,謝謝。 – GamerJ5

+1

您經常打電話給ReportProgress,並在更新的情況下敲擊UI線程。它跟不上。 –

回答

1

我沒仔細端詳的代碼,但我不明白爲什麼你使用秒錶,所以我拿出引用。我不確定在循環內多次啓動並在外部結束它會做什麼。

在第二個例子中使用這個詞END將comletely結束你的應用程序!很確定這就是你想要的。

試試你的第一個代碼此修改。關鍵是唯一的更新,如果變化是> = 5%:

 Using fs As New IO.FileStream(localfileamc, IO.FileMode.Create) 
      Dim buffer(2047) As Byte 
      Dim read As Integer = 0 
      Dim count As Integer 
      dim LastPct as Short = -5 
      dim Pct as Short = 0 
      Do 
       If amcworker.CancellationPending = True Then 
        e.Cancel = True 
        Return 
       End If 
       Pct = CShort(count/Length * 100 + 0.5) 
       if Pct>= (LastPct + 5) 
        amcworker.ReportProgress(Pct) 
        LastPCT= Pct 
       EndIf 
       read = responseStream.Read(buffer, 0, buffer.Length) 
       fs.Write(buffer, 0, read) 
       count += read 
      Loop Until read = 0 
      amcworker.ReportProgress(100) 
      responseStream.Close() 
      fs.Flush() 
      fs.Close() 
     End Using 
+0

完美工作,謝謝! – GamerJ5