我是一个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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的XAML代码:
<StackPanel>
<ProgressBar x:Name="prgBaseMap" Height="10" Visibility="Collapsed"/>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
虽然这适用于报告文件被复制,但它在我执行复制时不会显示进度.我究竟做错了什么 ?
***编辑,这不是带有进度条报告的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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
你可以像这样使用它:
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);
Run Code Online (Sandbox Code Playgroud)
该解决方案通过一次手动复制10k字节的文件内容来工作(该CopyStream方法).每次更新进度条.
在开始时,它将源文件的总长度相加,以便能够计算相对进度.
该CopyFiles方法将通过调用相对于进度的回调来向调用者报告进度10000.0.这就是进度条需要最大为10000.0的原因.
10000.0您可以使用输入文件的长度总和,而不是使用double值.这允许您还报告复制的字节总数.
在这种情况下,您必须计算调用者的长度总和.
| 归档时间: |
|
| 查看次数: |
4455 次 |
| 最近记录: |