Fre*_*red 6 c# math file-copying
我有一个应用程序,通过网络将大量文件复制到文件服务器(而不是Web).我试图显示剩余时间的一半估计.
我已经看了很多关于SO的文章,但问题得到了解决,我没有尝试过我真正想做的事情.我希望估计的剩余时间相对稳定IE不会在整个地方跳转,这取决于波动的传输速度.
所以我看到的第一个解决方案是计算传输速度,以每秒字节数为单位
double bytePerSec = totalBytesCopied / TimeTaken.TotalSeconds;
Run Code Online (Sandbox Code Playgroud)
然后将剩余的总字节除以传输速率.
double secRemain = (totalFileSizeToCopy - totalBytesCopied) / bytePerSec;
Run Code Online (Sandbox Code Playgroud)
我认为,一旦复制了几MB,剩余的时间会变得更加稳定(尽管期望它会改变.但事实并非如此,它的不稳定性和跳跃遍布整个地方.
然后我在SO上尝试了一个解决方案....
double secRemain = (TimeTaken.TotalSeconds / totalBytesCopied) * (totalFileSizeToCopy - totalBytesCopied);
Run Code Online (Sandbox Code Playgroud)
这是一个类似的计算,但希望它可能有所作为!
所以现在我有点想我需要从不同的角度来看待这个问题.IE使用平均值?使用某种倒数计时器并重置每隔一段时间的时间?只是寻找已经遇到过这个问题的人的意见或建议.
这里是你将如何异步复制文件的工作示例D:\dummy.bin来D:\dummy.bin.copy,与定时器拍摄每秒传输速率的快照.
根据该数据,我只需从最多30个快照(最新的第一个)获取平均传输速率.由此我可以粗略估计传输文件其余部分所需的时间.
此示例按原样提供,不支持在1次操作中复制多个文件.但它应该给你一些想法.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
public class Program
{
public static void Main(string[] args)
{
var sourcePath = @"D:\dummy.bin";
var destinationPath = @"D:\dummy.bin.copy";
var sourceFile = new FileInfo(sourcePath);
var fileSize = sourceFile.Length;
var currentBytesTransferred = 0L;
var totalBytesTransferred = 0L;
var snapshots = new Queue<long>(30);
var timer = new System.Timers.Timer(1000D);
timer.Elapsed += (sender, e) =>
{
// 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 = fileSize - totalBytesTransferred;
Console.WriteLine("Average speed: {0:#} MBytes / second", averageSpeed / (1024 * 1024));
if (averageSpeed > 0)
{
var timeLeft = TimeSpan.FromSeconds(bytesLeft / averageSpeed);
var timeLeftRounded = TimeSpan.FromSeconds(Math.Round(timeLeft.TotalSeconds));
Console.WriteLine("Time left: {0}", timeLeftRounded);
}
else
{
Console.WriteLine("Time left: Infinite");
}
};
using (var inputStream = sourceFile.OpenRead())
using (var outputStream = File.OpenWrite(destinationPath))
{
timer.Start();
var buffer = new byte[4096];
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 =>
{
outputStream.EndWrite(asyncWriteResult);
currentBytesTransferred = Interlocked.Add(ref currentBytesTransferred, numBytes);
totalBytesTransferred = Interlocked.Add(ref totalBytesTransferred, numBytes);
mre.Set();
}, null);
}, null);
mre.WaitOne(timeout);
} while (numBytes != 0);
timer.Stop();
}
}
}
Run Code Online (Sandbox Code Playgroud)