[英]WPF Showing progress bar during async file copy
我是wpf newb,所以這個問題可能很簡單。 我正在嘗試將文件從一個文件夾復制到另一個文件夾。 我想在復制過程中顯示進度條。
我的代碼是這樣的:
if (!System.IO.File.Exists(basemapDest))
{
await Copier.CopyFiles(new Dictionary<string, string>
{
{basemapSrc, basemapDest},
}, prog => prgBaseMap.Value = prog);
}
public static class Copier
{
public static async Task CopyFiles(Dictionary<string, string> files, Action<int> progressCallback)
{
for (var x = 0; x < files.Count; x++)
{
var item = files.ElementAt(x);
var from = item.Key;
var to = item.Value;
using (var outStream = new FileStream(to, FileMode.Create, FileAccess.Write, FileShare.Read))
{
using (var inStream = new FileStream(from, FileMode.Open, FileAccess.Read, FileShare.Read))
{
long fileLength = from.Length;
await inStream.CopyToAsync(outStream);
}
}
progressCallback((int)((x + 1) / files.Count) * 100);
}
}
}
我的XAML代碼:
<StackPanel>
<ProgressBar x:Name="prgBaseMap" Height="10" Visibility="Collapsed"/>
</StackPanel>
雖然此功能可用於報告文件已被復制,但在執行復制時不會顯示進度。 我究竟做錯了什么 ?
***編輯,這不是帶有進度條報告的stream.copyto的副本
所引用的問題使用的是BackgroundWorker,如今,許多人認為它已經過時了。 這個問題是關於使用新的.NET異步模型的。 我希望所提供的解決方案對其他人也有用。
這是一個解決方案,可讓您在復制文件時顯示進度:
public static class Copier
{
public static async Task CopyFiles(Dictionary<string, string> files, Action<double> progressCallback)
{
long total_size = files.Keys.Select(x => new FileInfo(x).Length).Sum();
long total_read = 0;
double progress_size = 10000.0;
foreach(var item in files)
{
long total_read_for_file = 0;
var from = item.Key;
var to = item.Value;
using (var outStream = new FileStream(to, FileMode.Create, FileAccess.Write, FileShare.Read))
{
using (var inStream = new FileStream(from, FileMode.Open, FileAccess.Read, FileShare.Read))
{
await CopyStream(inStream , outStream, x =>
{
total_read_for_file = x;
progressCallback(((total_read + total_read_for_file)/ (double)total_size) * progress_size);
} );
}
}
total_read += total_read_for_file;
}
}
public static async Task CopyStream(Stream from, Stream to, Action<long> progress)
{
int buffer_size = 10240;
byte[] buffer = new byte[buffer_size];
long total_read = 0;
while (total_read < from.Length)
{
int read = await from.ReadAsync(buffer, 0, buffer_size);
await to.WriteAsync(buffer, 0, read);
total_read += read;
progress(total_read);
}
}
}
您可以像這樣使用它:
var dictionary = new Dictionary<string, string>
{
{"c:\\source_file1.dat", "c:\\destination_file1.dat"},
{"c:\\source_file2.dat", "c:\\destination_file2.dat"},
};
prgBaseMap.Maximum = 10000.0;
await Copier.CopyFiles(dictionary, prog => prgBaseMap.Value = prog);
此解決方案通過一次手動復制10k字節的文件內容來工作( CopyStream
方法)。 並且每次更新進度條。
首先,它將求和源文件的總長度,以便能夠計算相對進度。
CopyFiles
方法將通過調用相對於10000.0
的進度來向調用方報告進度。 這就是進度條最多需要達到10000.0的原因。
可以使用輸入文件的長度總和代替使用10000.0
的雙10000.0
值。 這樣,您還可以報告已復制字節的總數。
在這種情況下,您將必須計算調用方的長度總和。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.