【发布时间】:2009-10-19 07:13:45
【问题描述】:
作为我正在开发的应用程序的一项功能,我需要显示向/从服务器上传/下载文件的总估计时间。
如何从客户端机器获取下载/上传到服务器的速度。
我认为如果我能够获得速度,那么我可以通过 -->
来计算时间例如 --- 对于 200 Mb 文件 = 200(1024 kb) = 204800 kb 和 除以 204800 Mb / 速度 Kb/s = "x" 秒
【问题讨论】:
标签: c# networking
作为我正在开发的应用程序的一项功能,我需要显示向/从服务器上传/下载文件的总估计时间。
如何从客户端机器获取下载/上传到服务器的速度。
我认为如果我能够获得速度,那么我可以通过 -->
来计算时间例如 --- 对于 200 Mb 文件 = 200(1024 kb) = 204800 kb 和 除以 204800 Mb / 速度 Kb/s = "x" 秒
【问题讨论】:
标签: c# networking
上传/下载速度不是服务器的静态属性,它取决于您的特定连接,也可能随时间而变化。我见过的大多数应用程序都会在很短的时间窗口内进行估计。这意味着他们开始下载/上传并测量数据量,比如说 10 秒。然后将其作为当前传输速度并用于计算剩余时间(例如 2500kB / 10s -> 250Kb/s)。时间窗口不断移动并重新计算,以保持计算准确到当前速度。
虽然这是一种非常基本的方法,但在大多数情况下都能很好地发挥作用。
【讨论】:
试试这样的:
int chunkSize = 1024;
int sent = 0
int total = reader.Length;
DateTime started = DateTime.Now;
while (reader.Position < reader.Length)
{
byte[] buffer = new byte[
Math.Min(chunkSize, reader.Length - reader.Position)];
readBytes = reader.Read(buffer, 0, buffer.Length);
// send data packet
sent += readBytes;
TimeSpan elapsedTime = DateTime.Now - started;
TimeSpan estimatedTime =
TimeSpan.FromSeconds(
(total - sent) /
((double)sent / elapsedTime.TotalSeconds));
}
【讨论】:
这只是切线相关,但我假设如果您要计算剩余的总时间,您可能还会将其显示为某种进度条。如果是这样,您应该阅读 Chris Harrison 关于感知差异的这篇论文。这是直接从他的论文中得出的结论(重点是我的)。
不同的进度条行为似乎对用户对流程持续时间的感知有显着影响。通过最大限度地减少负面行为并整合积极行为,可以有效地使进度条及其相关流程更快。此外,如果可以重新排列多阶段操作的元素,则可以以更令人愉悦且看似更快的顺序重新排列各个阶段。
http://www.chrisharrison.net/projects/progressbars/ProgBarHarrison.pdf
【讨论】:
我不知道你为什么需要这个,但我会尽可能简单地询问用户他有什么连接类型。然后将文件大小除以速度,然后除以 8 得到秒数。
关键是您不需要处理能力来计算速度。微软在他们的网站上使用的函数可以根据文件大小计算大多数默认连接的速度,您可以在上传文件或手动输入文件时获得该速度。
同样,也许您还有其他需求,您必须计算即时上传...
【讨论】:
以下代码以分钟为单位计算剩余时间。
long totalRecieved = 0;
DateTime lastProgressChange = DateTime.Now;
Stack<int> timeSatck = new Stack<int>(5);
Stack<long> byteSatck = new Stack<long>(5);
using (WebClient c = new WebClient())
{
c.DownloadProgressChanged += delegate(object s, DownloadProgressChangedEventArgs args)
{
long bytes;
if (totalRecieved == 0)
{
totalRecieved = args.BytesReceived;
bytes = args.BytesReceived;
}
else
{
bytes = args.BytesReceived - totalRecieved;
}
timeSatck.Push(DateTime.Now.Subtract(lastProgressChange).Seconds);
byteSatck.Push(bytes);
double r = timeSatck.Average() * ((args.TotalBytesToReceive - args.BytesReceived) / byteSatck.Average());
this.textBox1.Text = (r / 60).ToString();
totalRecieved = args.BytesReceived;
lastProgressChange = DateTime.Now;
};
c.DownloadFileAsync(new Uri("http://www.visualsvn.com/files/VisualSVN-1.7.6.msi"), @"C:\SVN.msi");
}
【讨论】:
我想我已经有预计的下载时间了。
double timeToDownload = ((((totalFileSize/1024)-((fileStream.Length)/1024)) / Math.Round(currentSpeed, 2))/60);
this.Invoke(new UpdateProgessCallback(this.UpdateProgress), new object[] {
Math.Round(currentSpeed, 2), Math.Round(timeToDownload,2) });
在哪里
private void UpdateProgress(double currentSpeed, double timeToDownload)
{
lblTimeUpdate.Text = string.Empty;
lblTimeUpdate.Text = " At Speed of " + currentSpeed + " it takes " + timeToDownload +" minute to complete download";
}
当前速度的计算方式如下
TimeSpan dElapsed = DateTime.Now - dStart;
if (dElapsed.Seconds > 0) {currentSpeed = (fileStream.Length / 1024) / dElapsed.Seconds;
}
【讨论】: