我正在创建一个涉及将大量文件附加到单个文件末尾的应用程序...我正在使用带缓冲区的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
是否有更好/更快/更有效的方法来实现这一点,无论是将流量附加到另一个文件还是显示进度?感谢..
答案 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