WPF在异步文件复制期间显示进度条

我是一个wpf newb所以这个问题可能是微不足道的。 我正在尝试将文件从一个文件夹复制到另一个文件夹。 我想在复制过程中显示进度条。

我的代码是这样的:

if (!System.IO.File.Exists(basemapDest)) { await Copier.CopyFiles(new Dictionary { {basemapSrc, basemapDest}, }, prog => prgBaseMap.Value = prog); } public static class Copier { public static async Task CopyFiles(Dictionary files, Action 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代码:

    

虽然这适用于报告文件被复制,但它在我执行复制时不会显示进度。 我究竟做错了什么 ?

***编辑,这不是带有进度条报告的stream.copyto的副本

引用的问题是使用BackgroundWorker,这些天被许多人认为是过时的。 这个问题是关于使用.NET的新异步模型。 我希望所提供的解决方案也certificate对其他人有用。

这是一个允许您在复制文件时显示进度的解决方案:

 public static class Copier { public static async Task CopyFiles(Dictionary files, Action 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 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 { {"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的double值。 这允许您报告复制的字节总数。

在这种情况下,您必须计算调用者的长度总和。