2013-07-31 74 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