【发布时间】:2015-06-30 02:35:08
【问题描述】:
我需要复制一些大文件并通过进度条将进度报告回 UI。
我买了“C# 5.0 in a Nutshell”。我在第 597 页。我一直在阅读有关并行编程的内容。根据本书中的一些示例,我正在尝试完成我认为很简单的事情,但我真的很挣扎。我的理解肯定有一些差距。这就是我发布这个问题的原因。
我研究过后台工作人员,但在尝试取得进展时发现自己遇到了跨线程编译器错误。
我研究了异步命令,但发现自己误解了 lambda 表达式。那,或者如何从按钮单击异步实际执行任务的代码,同时仍将进度报告回 UI 线程。
我在这里、MSDN、codeproject 上倾注了许多现有的问题/答案,我自己在这里问了一些问题,并让他们投了反对票。我只需要一个简单的例子,我可以把我的大脑包裹起来,我会顺利进行的。
我确信我的答案是异步、Task.Run、File.Copy(可能是 StreamReader/StreamWriter 类)和 IProgress。我在两周的研究和反复试验中发现的问题/答案要么不完整,要么对于某些特定场景来说过于宽泛/过于具体。
我只需要一个带有进度条的 UI 工作示例,以及一个在新线程中执行代码以复制一组大文件(或仅一个大文件)并报告进度的按钮。从那里,我可以使用它并根据我的需要对其进行调整,并进一步加深我的整体理解。
代码改编自克林特的回答,但仍未正确更新进度
此适配在异步任务中复制文件,但仅在文件复制后将进度从 0 更新到 100%。因为我正在处理大文件,所以基于文件数量的处理进度是不够的。
到目前为止,我还没有找到或尝试过在为大文件的字节进度 %-age 更新字节时异步执行复制的地址。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.IO;
namespace CopyProgressWorking
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
string srcFile = @"C:\temp\BigFile.txt";
string dstFile = @"C:\temp\temp2\BigFile.txt";
button1.Click += (s, e) => DoCopy(srcFile, dstFile);
}
public 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 size = inStream.Position;
Console.WriteLine("Filesize is {0}", size);
await inStream.CopyToAsync(outStream);
}
}
progressCallback((int)((x + 1) / files.Count) * 100);
}
}
public async void DoCopy(string srcFile, string dstFile)
{
label1.Text = "Copying " + srcFile;
await CopyFiles(new Dictionary<string, string>
{
{srcFile, dstFile}
},
prog =>
{
Invoke((MethodInvoker)delegate {
progressBar1.Value = prog;
if (prog >= 100)
{
label1.Text = "Copy complete!";
}
});
});
}
}
}
【问题讨论】:
-
首先,您将无法使用
File.Copy,除非您只想报告文件之间的进度。如果要在复制单个文件期间报告进度,则必须手动将数据从一个FileStream复制到另一个,或者使用非托管方法。 -
我很乐意获取文件的总字节数或一组文件的总字节数并报告该进度。看起来 CLR 已经有了这样一种我可以利用的方法?
-
字典
文件和 var item = files.ElementAt(x);不能真正工作,除非另有说明,否则不订购字典。 -
你有没有最终得到这个工作?如果是这样,示例是否像您在任何地方的 github 上寻找的那样?
标签: c# multithreading asynchronous system.io.file