1

我正在制作一个涉及将大量文件附加到单个文件末尾的应用程序......我正在使用带有缓冲区的文件流类以避免将整个文件加载到内存中,但是,我想显示进度复制每个单独的文件,以及当前文件的名称......这很容易,但是,如果每个文件非常小,在 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

在将一个文件流式附加到另一个文件并显示进度方面,是否有更好/更快/更有效的方法来做到这一点?谢谢..

4

1 回答 1

4

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

代码示例:

首先确保你有一个BackgroundWorker并且它被设置为报告进度(通过将属性设置WorkerReportsProgressTrue

' 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
于 2013-06-17T21:13:05.407 回答