c# - 剩余时间基于进度?

标签 c# winforms .net-4.0 timer countdown

我想按以下格式输出流程的剩余时间:

d hh:mm:ss

当进程开始时,它设置一个DateTime startTime变量为当前时间。

我的 GUI 上有计时器,每秒更新一个标签,这是我必须计算剩余时间的内容:

TimeSpan timeRemaining = TimeSpan.FromTicks(DateTime.Now.Subtract(startTime).Ticks * (iProgress.Maximum - iProgress.Value) / iProgress.Value);

并在标签上使用:

labelTimeRemaining.Text = timeRemaining.ToString(@"d\ hh\:mm\:ss");

然而,显示的时间变化在进入稳定模式时非常奇怪地跳跃了几分钟。

我知道它应该在开始时跳跃,但它应该在某个时候稳定下来,对吧?

我每秒处理大约 1~3 条记录,但每次更新剩余时间会增加 10~20 分钟。

我做错了什么或者我该如何解决这个问题?

如果您需要更多信息或代码,请告诉我。

更新

下面是我使用的部分代码:

private Stopwatch _timer = new Stopwatch();
private int _total = 0;
private int _current = 0;

启动线程或任务:

private void MyTask()
{
    _timer.Reset();
    _timer.Start();
    for (int i = 0; i < _total; i++)
    {
        _current++;
        Thread.Sleep(500);
    }
    _timer.Stop();
}

使用以下函数创建一个 winforms 计时器以每秒运行一次:

if (_timer.IsRunning && _current > 0)
{
    float elapsedMin = ((float)_timer.ElapsedMilliseconds / 1000) / 60;
    float minLeft = (elapsedMin / _current) * (_total - _current);
    TimeSpan eta = TimeSpan.FromMinutes(minLeft);
    iStatus.Text = eta.ToString(@"d\ hh\:mm\:ss");
}

最佳答案

根据您提供的评论,当您处理 10K 到 1000 万条记录时,如您所见,波动相当大。这是将显示波动的测试示例。

DateTime dt = DateTime.Now;
Thread.Sleep(3000);
TimeSpan ts = TimeSpan.FromTicks(DateTime.Now.Subtract(dt).Ticks * (100000 - 7) / 7);
Debug.WriteLine(ts.ToString());
Thread.Sleep(1000);
ts = TimeSpan.FromTicks(DateTime.Now.Subtract(dt).Ticks * (100000 - 9) / 9);
Debug.WriteLine(ts.ToString());

另外,即使你处理了整数除法

DateTime dt = DateTime.Now;
Thread.Sleep(3000);
TimeSpan ts = TimeSpan.FromTicks((long)((double)DateTime.Now.Subtract(dt).Ticks * (100000.0 - 7.0) / 7.0));
Debug.WriteLine(ts.ToString());

Thread.Sleep(1000);
ts = TimeSpan.FromTicks((long)((double)DateTime.Now.Subtract(dt).Ticks * (100000.0 - 9.0) / 9.0));
Debug.WriteLine(ts.ToString());

但是如果您可以将您的记录数标准化为百分比。假设您有 100K 条记录,1K 是百分之一,大约 1000/2/60 大约 8 分钟完成。 32 分钟后,您将完成 4%。又过了 24 分钟,你将完成 6%,你将完成大约 9%,但可以说是 10%。再过 30 分钟后,您应该完成了 14%。现在,如果你很少更新你的文本框,用户会产生你真的知道需要多长时间的错觉,你最终会改变一两个小时的时间,但每分钟或每改变一个百分比(有你曾经在 Windows 上复制过 30GB?)

DateTime dt1 = DateTime.Now;
DateTime dt2 = DateTime.Now;
dt2 = dt2.AddMinutes(32);
ts = TimeSpan.FromTicks(dt2.Subtract(dt1).Ticks * (100 - 4) / 4);
Debug.WriteLine(ts.ToString());

dt2 = dt2.AddMinutes(16);
ts = TimeSpan.FromTicks(dt2.Subtract(dt1).Ticks * (100 - 6) / 6);
Debug.WriteLine(ts.ToString());

dt2 = dt2.AddMinutes(24);
ts = TimeSpan.FromTicks(dt2.Subtract(dt1).Ticks * (100 - 10) / 10);
Debug.WriteLine(ts.ToString());

dt2 = dt2.AddMinutes(30);
ts = TimeSpan.FromTicks(dt2.Subtract(dt1).Ticks * (100 - 14) / 14);
Debug.WriteLine(ts.ToString());

关于c# - 剩余时间基于进度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13040659/

相关文章:

c# - 你必须调用 Xamarin.Forms.Init();使用前

c# - mvvmlight wpf 如何提高框架源属性 wpf c#

c# - 调用存储在字符串变量中的函数

.net - winform中的TreeView节点映射

c# - 检查按钮是否在特定区域

.net - 在 .net 中获取连接到 PC 的硬盘的唯一 ID

asp.net - 在 .NET 4 MVC 2 中启用 Windows 身份验证

visual-studio-2010 - 安装后报告缺少 System.Data.SQLite.dll

c# - 如何使用 Windows.Web.Http 下载和存储图像?

dynamic - .NET 4.0 - "dynamic"关键字