gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 19:55:48 25 4
gpt4 key购买 nike

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

我的代码是这样的:

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 with progress bar reporting 的副本

引用的问题是使用 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 的原因。

您可以使用输入文件的长度总和,而不是使用 double 值 10000.0。这使您还可以报告复制的字节总数。

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

关于c# - WPF 在异步文件复制期间显示进度条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33726729/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com