vb.net如何在while循环中显示进度?

时间:2013-06-17 21:01:38

标签: vb.net file copy

我正在创建一个涉及将大量文件附加到单个文件末尾的应用程序...我正在使用带缓冲区的filestream类来避免将整个文件加载到内存中,但是,我想要显示每个单独文件复制时的进度,以及当前文件的名称......这很容易,但是,如果每个文件非常小,在foreach循环接缝内这样做会大大降低性能。

这是代码:

  Public Function StreamAppendFileToFile(ByVal f1 As String, ByVal f2 As String)
        Dim bytesRead As Integer
        Dim nn As New FileInfo(f1)
        CurrentFsize = nn.Length

        Dim buffer(40096) As Byte
        Using inFile As New System.IO.FileStream(f1, IO.FileMode.Open, IO.FileAccess.Read)
            Using outFile As New System.IO.FileStream(f2, IO.FileMode.Append, IO.FileAccess.Write)
                Do
                    bytesRead = inFile.Read(buffer, 0, 40096)
                    outFile.Write(buffer, 0, bytesRead)
                    Application.DoEvents()
                Loop While bytesRead > 0
            End Using
        End Using
    End Function

如果我把这样的东西执行时间加倍

Public Function StreamAppendFileToFile(ByVal f1 As String, ByVal f2 As String)
        Dim bytesRead As Integer
        Dim nn As New FileInfo(f1)
        CurrentFsize = nn.Length

        Dim buffer(40096) As Byte
        Using inFile As New System.IO.FileStream(f1, IO.FileMode.Open, IO.FileAccess.Read)
            Using outFile As New System.IO.FileStream(f2, IO.FileMode.Append, IO.FileAccess.Write)
                Do
                    bytesRead = inFile.Read(buffer, 0, 40096)
                    **Progressbar1.value = Math.Round((bytesRead / CurrentFsize) * 100)**
                    **Application.Doevents()**
                    outFile.Write(buffer, 0, bytesRead)
                    Application.DoEvents()
                Loop While bytesRead > 0
            End Using
        End Using
    End Function

是否有更好/更快/更有效的方法来实现这一点,无论是将流量附加到另一个文件还是显示进度?感谢..

1 个答案:

答案 0 :(得分:4)

如果操作需要很长时间,我建议将操作移到另一个线程。您可以使用BackgroundWorker来执行此操作(并使用事件DoWork执行操作,并使用ProgressChanged事件向UI报告进度。

代码示例:

首先确保您有一个BackgroundWorker并设置为报告进度(通过将属性WorkerReportsProgress设置为True

' This class is used to pass the information to the BackgroundWorker DoWork event
Private Class IOFilesInfo
    Public Property InFile As String
    Public Property OutFile As String
End Class

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    ' Start the BackgroundWorker if it isn't started yet
    If Not BackgroundWorker1.IsBusy Then
        Dim filesInfo As New IOFilesInfo() With {.InFile = "in.txt", .OutFile = "out.txt"}
        BackgroundWorker1.RunWorkerAsync(filesInfo)
    End If
End Sub

Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    Dim worker As BackgroundWorker = DirectCast(sender, BackgroundWorker)
    Dim filesInfo As IOFilesInfo = DirectCast(e.Argument, IOFilesInfo)

    ' Get the file info for the input file (the filesize)
    Dim inFileFileInfo As New FileInfo(filesInfo.InFile)
    Dim inFileFileSize As Long = inFileFileInfo.Length

    ' Keep the progress, total amount of bytes read => you could also keep the progress percentage
    Dim totalBytesRead As Integer = 0

    Dim bytesRead As Integer
    Dim buffer(10) As Byte
    Using inFile As New System.IO.FileStream(filesInfo.InFile, IO.FileMode.Open, IO.FileAccess.Read)
        Using outFile As New System.IO.FileStream(filesInfo.OutFile, IO.FileMode.Append, IO.FileAccess.Write)
            Do
                bytesRead = inFile.Read(buffer, 0, 10)
                outFile.Write(buffer, 0, bytesRead)

                ' Add the bytesRead to the total and report the progress as a percentage
                totalBytesRead += bytesRead
                worker.ReportProgress(Convert.ToInt32(totalBytesRead \ inFileFileSize) * 100)
            Loop While bytesRead > 0
        End Using
    End Using
End Sub

Private Sub BackgroundWorker1_ProgressChanged(sender As System.Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    ProgressBar1.Value = e.ProgressPercentage
End Sub