我希望在复制大量文件(也是大文件)时获得准确的传输速率和剩余时间。这应该通过主进度条和定义的速度和时间标签可视化。
在例程开始时,后台工作者遍历给定目录并构建包含源和目标路径的字典。
此处找到的机制:Calculating Time Remaining on File Copy。 (答案来自Steven Liekens)
问题是,100%的进展从未达到,有时以96%-98%完成,但从未达到100%。也许使用不同的方法计算的(递归)目录计算的totalBytes存在差异。
接下来的一点是,显示的传输速率是正确的,如果它乘以10 ....所以我的ssd机器显示的传输速率显示30 MB / s,更像是300 MB / s。显示的速率肯定是错误的。
这里有2个问题: 1.)错误计算进度 2.)错误的传输速率计算(速度相当不错)
有人能指出原因吗?
private void CopyFileList(DoWorkEventArgs eWorker)
{
if (fileWorker.CancellationPending)
{
eWorker.Cancel = true;
}
else
{
var totalBytes = GetTotalBytes();
var currentBytesTransferred = 0L;
var totalBytesTransferred = 0L;
var snapshots = new Queue<long>(30);
var timer = new System.Timers.Timer(100D);
foreach (var file in FilesToCopy)
{
var sourcePath = file.Key;
var destinationPath = file.Value;
var sourceFile = new FileInfo(sourcePath);
//var fileSize = sourceFile.Length;
timer.Elapsed += (sender, e) =>
{
if (fileWorker.CancellationPending)
{
eWorker.Cancel = true;
}
else
{
// Remember only the last 30 snapshots; discard older snapshots
if (snapshots.Count == 30)
{
snapshots.Dequeue();
}
snapshots.Enqueue(Interlocked.Exchange(ref currentBytesTransferred, 0L));
var averageSpeed = snapshots.Average();
var bytesLeft = totalBytes - totalBytesTransferred;
var speedText = string.Format("{0:#} MB/s", averageSpeed / (1024 * 1024));
var timeLeftText = string.Empty;
if (averageSpeed > 0)
{
var timeLeft = TimeSpan.FromSeconds(bytesLeft / averageSpeed);
var timeLeftRounded = TimeSpan.FromSeconds(Math.Round(timeLeft.TotalSeconds));
timeLeftText = string.Format("{0}", timeLeftRounded);
}
else
{
timeLeftText = ("-infinite-");
}
Console.WriteLine(speedText);
Console.WriteLine("Time Left: " + timeLeftText);
fileWorker.ReportProgress((currentBytesTransferred / maximum) * 100));
}
};
using (var inputStream = sourceFile.OpenRead())
using (var outputStream = File.OpenWrite(destinationPath))
{
timer.Start();
var buffer = new byte[4096 * 8];
var numBytes = default(int);
var numBytesMax = buffer.Length;
var timeout = TimeSpan.FromMinutes(10D);
do
{
var mre = new ManualResetEvent(false);
inputStream.BeginRead(buffer, 0, numBytesMax, asyncReadResult =>
{
numBytes = inputStream.EndRead(asyncReadResult);
outputStream.BeginWrite(buffer, 0, numBytes, asyncWriteResult =>
{
if (fileWorker.CancellationPending)
{
eWorker.Cancel = true;
return;
}
else
{
outputStream.EndWrite(asyncWriteResult);
currentBytesTransferred = Interlocked.Add(ref currentBytesTransferred, numBytes);
Results.SizeProgressed = totalBytesTransferred;
totalBytesTransferred = Interlocked.Add(ref totalBytesTransferred, numBytes);
mre.Set();
}
}, null);
}, null);
mre.WaitOne(timeout);
} while (numBytes != 0);
timer.Stop();
}
}
}
}
示例:
将目录(21个目录,228个文件,总计:326MB)复制到NAS: 12.4434796 s和报告的平均速度为2-3 MB / s。但复制速度快了近10倍。
答案 0 :(得分:0)
我遇到了和你一样的问题。我检查了您的两个问题并相应地更改了代码。我稍微修改了您的代码以计算剩余时间和 MB/s 速度。
private void CopyFileList(DoWorkEventArgs eWorker)
{
if (fileWorker.CancellationPending)
{
eWorker.Cancel = true;
}
else
{
var totalBytesTransferredInSecond = 0L;
var totalBytes = GetTotalBytes();
var currentBytesTransferred = 0L;
var totalBytesTransferred = 0L;
var timer = new System.Timers.Timer(1000D);
foreach (var file in FilesToCopy)
{
var sourcePath = file.Key;
var destinationPath = file.Value;
var sourceFile = new FileInfo(sourcePath);
//var fileSize = sourceFile.Length;
timer.Elapsed += (sender, e) =>
{
if (fileWorker.CancellationPending)
{
eWorker.Cancel = true;
}
else
{
// Remember only the last 30 snapshots; discard older snapshots
var bytesLeft = totalBytes - totalBytesTransferred;
var speedText = string.Format("{0:#} MB/s", totalBytesTransferredInSecond / (1024 * 1024));
var timeLeftText = string.Empty;
if (totalBytesTransferredInSecond > 0)
{
var timeLeft = TimeSpan.FromSeconds(bytesLeft / totalBytesTransferredInSecond);
var timeLeftRounded = TimeSpan.FromSeconds(Math.Round(timeLeft.TotalSeconds));
timeLeftText = string.Format("{0}", timeLeftRounded);
}
else
{
timeLeftText = ("-infinite-");
}
Console.WriteLine(speedText);
Console.WriteLine("Time Left: " + timeLeftText);
totalBytesTransferredInSecond = 0;
}
};
using (var inputStream = sourceFile.OpenRead())
using (var outputStream = File.OpenWrite(destinationPath))
{
timer.Start();
var buffer = new byte[1024 * 1024];
var numBytes = default(int);
var numBytesMax = buffer.Length;
var timeout = TimeSpan.FromMinutes(10D);
do
{
var mre = new ManualResetEvent(false);
inputStream.BeginRead(buffer, 0, numBytesMax, asyncReadResult =>
{
numBytes = inputStream.EndRead(asyncReadResult);
outputStream.BeginWrite(buffer, 0, numBytes, asyncWriteResult =>
{
if (fileWorker.CancellationPending)
{
eWorker.Cancel = true;
return;
}
else
{
outputStream.EndWrite(asyncWriteResult);
currentBytesTransferred = Interlocked.Add(ref currentBytesTransferred, numBytes);
totalBytesTransferredInSecond += currentBytesTransferred;
Results.SizeProgressed = totalBytesTransferred;
totalBytesTransferred = Interlocked.Add(ref totalBytesTransferred, numBytes);
mre.Set();
fileWorker.ReportProgress((currentBytesTransferred / maximum) * 100));
}
}, null);
}, null);
mre.WaitOne(timeout);
} while (numBytes != 0);
timer.Stop();
}
}
}
}
请注意,我将计时器设置为 1000 毫秒。如果要将计时器设置为 100 毫秒,则必须将平均速度乘以 10。
totalBytesTransferredInSecond = totalBytesTransferredInSecond * 10;
var speedText = string.Format("{0:#} MB/s", totalBytesTransferredInSecond / (1024 * 1024));