带进度条的异步文件夹复制

Async folder copy with progress bar

提问人:Minesh 提问时间:10/30/2023 最后编辑:Palle DueMinesh 更新时间:10/30/2023 访问量:52

问:

我在网上搜索并找到了 c# 代码来复制带有进度条的异步文件,该代码运行良好。现在我正在尝试复制一个包含多个文件的文件夹。我添加了一个额外的进度条,但新的进度条无需等待即可快速完成。

我把代码放在这里:

private void button1_Click(object sender, EventArgs e)
{
    var _source = txtSource.Text;
    var _destination = txtDestination.Text;

    Task.Run(() =>
    {
        CopyFoldersRecursively(_source, _destination, x => progressBar1.BeginInvoke(new Action(() => { progressBar1.Value = x; })));
    }).GetAwaiter().OnCompleted(() => progressBar1.BeginInvoke(new Action(() => { progressBar1.Value = 100; })));
}

public  void CopyFoldersRecursively(string sourcePath, string targetPath, Action<int> progressCallback)
{
    try
    {
        // Now Create all of the directories
        foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
        {
            Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPath));
        }

        // Copy all the files & Replaces any files with the same name
        foreach (string newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories))
        {
            var _source = new FileInfo(newPath);
            var _destination = new FileInfo(targetPath + @"\" + Path.GetFileName(_source.ToString()));

            Task.Run(() =>
            {
                _source.CopyTo(_destination, x => progressBar2.BeginInvoke(new Action(() => { progressBar2.Value = x; lblPercent2.Text = x.ToString() + "%"; })));
            }).GetAwaiter().OnCompleted(() => progressBar2.BeginInvoke(new Action(() => { progressBar2.Value = 100; lblPercent2.Text = "100%"; })));
        }                
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

public static class FileInfoExtension
{
    public static void CopyTo(this FileInfo file, FileInfo destination, Action<int> progressCallback)
    {
        const int bufferSize = 1024 * 1024;
        byte[] buffer = new byte[bufferSize], buffer2 = new byte[bufferSize];
        bool swap = false;
        int progress = 0, reportedProgress = 0, read = 0;
        long len = file.Length;
        float flen = len;
        Task writer = null;
        using (var source = file.OpenRead())
            using (var dest = destination.OpenWrite())
            {
                dest.SetLength(source.Length);
                for (long size = 0; size < len; size += read)
                {
                    if ((progress = ((int)((size / flen) * 100))) != reportedProgress)
                        progressCallback(reportedProgress = progress);
                    read = source.Read(swap ? buffer : buffer2, 0, bufferSize);
                    writer?.Wait();
                    writer = dest.WriteAsync(swap ? buffer : buffer2, 0, read);
                    swap = !swap;
                }
                writer?.Wait();
            }
    }
}
C# 异步 目录 复制 进度

评论

1赞 Good Night Nerd Pride 10/30/2023
尝试和 .您必须将返回类型更改为 to 而不是 。内部也需要改变。await Task.Run(() => _source.CopyTo(...await CopyFoldersRecursively(...CopyFoldersRecursively()async TaskvoidTask.Run(() =>button1_Click()Task.Run(async () =>
0赞 JonasH 10/30/2023
首先,异步方法在大多数情况下应该返回一个任务,以便调用方知道任务何时完成。其次,以这种方式执行并行复制可能会由于随机读取和写入而降低性能。第三,您可能应该使用它来处理与 UI 线程的同步。第四,您通常应该避免重新启动进度条,因此您可能应该计算要复制的总字节数,并报告到目前为止已复制的字节数。Progress<T>
0赞 Minesh 10/30/2023
我是这个概念的新手,所以仍在尝试应用。感谢您的帮助。

答: 暂无答案