我有以下代码,在某个表上运行“select”,需要每200毫秒监控一次
timerMonitoreoOrdenes = new System.Timers.Timer(FRECUENCIA_MONITOREO_ORDENES);
timerMonitoreoOrdenes.Elapsed += new ElapsedEventHandler(timerMonitoreoOrdenes_Elapsed);
timerMonitoreoOrdenes.Enabled = true;
timerMonitoreoOrdenes.AutoReset = true;
在timerMonitoreoOrdenes_Elapsed
方法中,我运行一个返回DataSet的存储过程
对于每一行,我创建一个存储在内存Queue
该程序旨在一直运行(如Windows服务),但程序运行几个小时后,我收到此异常
System.OutOfMemoryException:
in System.Threading.ExecutionContext.CreateCopy()
in System.Threading._TimerCallback.PerformTimerCallback(Object state)
我这样做的原因是因为有一个外部程序在状态= 0的DB上插入记录,我需要记录这些记录,处理它们并设置status = 1。有一些线程从队列中获取记录
重要的是要提到这是一个实时交易应用程序,信息中的1秒延迟太高
答案 0 :(得分:6)
当然,这很有可能。用AutoReset = true勾选的计时器是一个定时炸弹。如果Interval太短,事情会发生严重错误。使用200毫秒是非常危险的,dbase更新查询可能需要更长时间。特别是如果您要查找的列未编入索引。
即使前一个事件处理程序未完成,您的Elapsed事件处理程序也会再次运行。在另一个线程池线程上。每个线程将消耗一兆字节的内存,以及查询和处理所需的任何内容。这只是继续,创造更多的线程。线程池管理器将努力限制这一点,但允许运行的最大线程数非常高。足够高,导致任意代码最终被OOM覆盖。
使用AutoReset = false并在Elapsed事件处理程序的末尾再次调用Start()。并使用至少接近实际处理时间的合理间隔。并在该列上添加索引,以便dbase引擎不必查看表中的每条记录。
答案 1 :(得分:0)
您好我曾经这样做了一次,我不得不分割代码并制作Windows服务,我建议您也这样做,使用Windows服务每10分钟检查一次,每分钟或类似的事情,以及运行程序。
如果你正在使用Windows窗体,主系统将会崩溃很多次,我希望我能帮助你解决这个问题。
答案 2 :(得分:0)
您是否确定在不再需要计时器时通过调用Dispose()方法正确处理计时器?如果不这样做,就会造成内存泄漏。