基于进度的剩余时间?

时间:2012-10-23 23:03:53

标签: 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 Timer,每秒运行一次:

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");
}

1 个答案:

答案 0 :(得分:2)

根据您提供的评论,当您使用10K到10M的记录时,您可以看到波动相当大。以下是测试示例,它将向您显示波动。

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是1%,大约在1000/2/60左右完成。 32分钟后,您将完成4%。接下来你将完成6%,再过24分钟你将完成9%左右,但比如说10%。 30分钟后你应该完成14%。而现在,如果你很少更新你的textBox,那么用户会产生一种错觉,你真的知道需要多长时间,而你最终会改变一两个小时的时间,但每分钟或每一个百分比都会改变(有)你有没有在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());