1

私はこれを理解しようと頭を悩ませてきました。これがシナリオです。私は基本的に、イベントが発生するはずのさまざまな時間を含むソートされた静的リストを持っています。視覚化の場合:

+-----------------------+
|  Time  |  LastUpdate  |
|-----------------------|
|    1   |   03:10:00   | 0
|    2   |   03:10:00   | 1
|    2   |   03:10:00   | 2
|    3   |   03:10:00   | 3
|    3   |   03:10:00   | 4
|    4   |   03:10:00   | 5
+-----------------------+

したがって、このメソッドを初めて使用すると、lastTimeプロパティはnullになるため、「何らかの作業を行い」、lastTimeプロパティを現在の時刻に設定します。timeプロパティは、アイテムを再度実行する必要がある時期を示します。たとえば、要素0のalastTime03:10:00Timeは1であるため、で実行する必要があります03:11:00。要素1と2の両方でalastTime03:10:00使用し、両方でで実行する必要があり03:12:00ます。

これが私が行っていることの大まかな実装です:

public static IList<Item> _list;

public void DoSomething()
{
    while (true)
    {
        for (int i = 0; i < _list.Count; i++)
        {
            var item = new Item();

            if (DateTime.MinValue.Equals(_list[i].LastUpdate))
            {
                item = DoWork(_list[i].Url);
                _list[i].LastUpdate = item.LastUpdate;
                Console.WriteLine(item.Title + " @ " + item.LastUpdate + "; i = " + i);
            }
            else
            {
                var timeToSleep = ((_list[i].LastUpdate.AddMinutes(_list[i].Time)).Subtract(DateTime.Now));

                if (timeToSleep.TotalMilliseconds > 0)
                {
                    for (int j = 0; j < i; j++)
                    {
                        var lastRet = _list[j].LastUpdate.AddMinutes(_list[j].Time);
                        var nextFetch = DateTime.Now.Add(timeToSleep);

                        if (lastRet < nextFetch)
                        {
                            item = DoWork(_list[i].Url);
                            _list[i].LastUpdate = item.LastUpdate;
                            Console.WriteLine(item.Title + " @ " + item.LastUpdate + "; i = " + i);
                        }
                    }
                }

                if (timeToSleep.TotalMilliseconds > 0)
                {
                    Console.WriteLine("Sleeping until: " + DateTime.Now.Add(timeToSleep));
                    System.Threading.Thread.Sleep(timeToSleep);
                }

                item = DoWork(_list[i].Url);
                _list[i].LastUpdate = item.LastUpdate;
                Console.WriteLine(item.Title + " @ " + item.LastUpdate + "; i = " + i);
            }
        }

        Console.WriteLine("--------------------------");
    }
}

実行する必要のあるものがない場合は、リスト内の次の項目を更新する準備ができるまでスリープ状態になります。内側のforループは、頻繁に更新されるアイテムが、頻繁に更新されないアイテムが更新されるまで待機してから、再度更新されるのを防ぐために配置されています。理想的なシナリオでは、Sleepを呼び出す前に、上記の項目を更新する必要があるかどうかを確認します。現在のアイテムがスリープする前に、現在のアイテムより上のアイテムを更新する必要がある場合は、先に進んでそれらを更新します。そうでない場合、現在のアイテムはスリープを呼び出して、更新の準備ができるまで待機します。これが理にかなっていることを願っています。

私はこれについて完全に間違っていますか?これに対するより簡単な解決策はありますか?私はありとあらゆる提案を受け入れます。また、このリストは数千のアイテムに増える可能性があることに注意してください。前もって感謝します。

4

1 に答える 1

1

問題の説明を完全には理解していませんが、これは不必要に複雑に思えます。どうですか:

public static IList<Item> _list;

public void DoSomething()
{
    while (true)
    {
        DateTime minDate = DateTime.MaxValue;

        for (int i = 0; i < _list.Count; i++)
        {
            DateTime nextExecution = _list[i].LastUpdate.AddMinutes(_list[i].Time);

            if (nextExecution <= DateTime.Now)
            {
                var item = DoWork(_list[i].Url);
                _list[i].LastUpdate = item.LastUpdate;
                nextExecution = _list[i].LastUpdate.AddMinutes(_list[i].Time);
                Console.WriteLine(item.Title + " @ " + item.LastUpdate + "; i = " + i);
            }

            if (nextExecution < minDate)
                minDate = nextExecution;
        }

        TimeSpan timeToSleep = minDate.Subtract(DateTime.Now));

        if (timeToSleep.TotalMilliseconds > 0)
        {
            Console.WriteLine("Sleeping until: " + minDate);
            System.Threading.Thread.Sleep(timeToSleep);
        }
    }
}

タスクの数が多くなった場合は、次に計算された実行時間順に並べられたリンク リストを保持することができます。そうすれば、反復ごとにリスト全体をループする必要はありません。

于 2009-07-24T22:23:49.927 に答える