3

プロセスの残り時間を次の形式で出力したいと思います。

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

1 に答える 1

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 で約 8 分で完了します。32 分後には 4% 完了しています。次々と 6% 完了し、さらに 24 分後には約 9% 完了しますが、10% としましょう。さらに 30 分後、14% 完了しているはずです。そして今、テキストボックスをめったに更新しないと、ユーザーは、どれくらいの時間がかかるかを本当に知っているという錯覚を抱き、最終的に1〜2時間時間を変更することになりますが、1分ごとまたは変更されたすべてのパーセントでそれを行います( 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());
于 2012-10-24T00:29:01.803 に答える