我需要在预定义的时间以高效的方式运行数十万个函数,
我目前的代码是这样的:
class myclass
{
public DateTime NextTime = DateTime.Now;
Random rand = new Random();
public void DoStuff()
{
if (NeedToWork())
{
// do some complex stuff on a 2nd thread.
NextTime = DateTime.Now.AddSeconds(rand.Next(60, 3600));
}
}
public bool NeedToWork()
{
return DateTime.Now > NextTime;
}
}
从定时器运行的调用函数:
static List<myclass> mylist = new List<myclass>();
static void Activator()
{
foreach (var item in mylist)
{
item.DoStuff();
}
}
我的问题是当集合中有分配的项目时,遍历所有项目需要很长时间,导致某些 DoStuff() 函数在某些情况下运行延迟超过一分钟。
目前,“Activator”函数是从不同的线程同时调用的,以使延迟时间尽可能短,(必要的线程同步通过使用 Mutex
来处理)
我想到的2个解决方案:
- 而不是一个
List<myclass>
, 我可以有一本像Dictionary<DateTime, List<myclass>>
这样的字典,以 1 秒的精度,每秒运行适当的类对象,dictionay 将映射“nexttime”到“myclass”实例。 - 创建两个
List<>
s 或Queue<>
s 而不是一个列表,它们将被命名为“fastqueue”和“slowqueue”,slowqueue 将拥有所有对象,fastqueue 将拥有所有很快需要工作的项目,然后有一个专用线程循环通过慢队列, 并查看剩余时间放入fastqueue。
注意事项:
真正的代码没有任何随机数据决定下一次运行时间,它实际上是基于一些计算,这只是一个示例。
每个项目的运行时间不超过几分之一秒,并且每个项目在一个小时内最多只运行 4 次。 ram 和 cpu 功率不是问题,我已经测试并在不同区域进行了优化以使其适合,尽管此处并未显示所有代码。
- 唯一浪费 CPU 时间的是 return DateTime.Now > NextTime 这行
最佳答案
您可能想要维护一个排序的队列或工作树,按运行时间排序。
然后您的常规间隔计时器循环运行队列中的前 N 个项目,当一个项目超出当前间隔时间时停止,因为不需要进一步查看。
当生成要添加到队列的新工作时,使用排序的数据结构,插入应该正确放置它以保持排序。
(您还需要担心添加和删除队列时的线程安全问题。)
(仅供引用,调度算法有很多变体。)
作为另一个注意事项,虽然不确定它是否对您有用,但在使用这些基于时间的公式时,您可能会考虑拍摄 DateTime.Now 的快照以多次使用,否则您可以“如果此线程在调用 DateTime.Now 之间被中断,则松散“时间”
public void DoStuff(DateTime now)
{
if (NeedToWork(now))
{
// do some complex stuff on a 2nd thread.
NextTime = now.AddSeconds(rand.Next(60, 3600));
}
}
关于c# - 在预定义的时间高效运行数十万个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14105175/