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 的 a oflastTime03:10:00Time 为 1,因此需要在03:11:00lastTime03:10:0003: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 之前检查它上面的任何项目是否需要更新。如果当前项目之上的任何项目需要在当前项目休眠之前更新,则继续更新它们。如果没有,则当前项目将调用 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 回答