【发布时间】:2011-06-20 01:41:59
【问题描述】:
标准 System.Timers.Timer 行为存在问题。计时器以一定的时间间隔引发 Elapsed 事件。但是当 Elapsed 事件处理程序内的执行时间超过计时器间隔时,线程池开始排队事件处理。在我的情况下这是一个问题。这是因为我使用 Elapsed 事件处理程序从数据库中获取一些数据并对其进行处理,最后将结果保存回数据库。但是数据处理应该只提供一次。那么,有没有办法防止对 System.Timers.Timer 的 elapse 事件进行排队。
作为这个问题的说明,你可以考虑下一个测试程序:
public class EntryPoint
{
private static void TimeProc(object state, ElapsedEventArgs e)
{
Console.WriteLine("Current time {0} on the thread {1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(20000);
}
static void Main(string[] args)
{
Console.WriteLine("Press <Enter> for finishing\n\n");
ThreadPool.SetMaxThreads(10, 10);
System.Timers.Timer MyTimer = new System.Timers.Timer(1000);
MyTimer.Elapsed += new ElapsedEventHandler(TimeProc);
MyTimer.Start();
Console.ReadLine();
MyTimer.Stop();
}
}
可能的输出如下:
Current time 03.02.2011 0:00:09 on the thread 4
Current time 03.02.2011 0:00:10 on the thread 5
Current time 03.02.2011 0:00:12 on the thread 6
Current time 03.02.2011 0:00:13 on the thread 7
Current time 03.02.2011 0:00:14 on the thread 8
Current time 03.02.2011 0:00:15 on the thread 9
Current time 03.02.2011 0:00:16 on the thread 10
Current time 03.02.2011 0:00:17 on the thread 11
Current time 03.02.2011 0:00:18 on the thread 12
Current time 03.02.2011 0:00:19 on the thread 13
Current time 03.02.2011 0:00:30 on the thread 4
Current time 03.02.2011 0:00:30 on the thread 5
可能的解决方案:
1) 灵感来自:C# Timer vs Thread in Service
关于上述示例,这里有一个类似的代码:
public class EntryPoint
{
private static System.Timers.Timer MyTimer;
private static void TimeProc(object state, ElapsedEventArgs e)
{
Console.WriteLine("Current time {0} on the thread {1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(20000);
MyTimer.Enabled = true;
}
static void Main(string[] args)
{
Console.WriteLine("Press <Enter> for finishing\n\n");
ThreadPool.SetMaxThreads(10, 10);
MyTimer = new System.Timers.Timer(1000);
MyTimer.AutoReset = false;
MyTimer.Elapsed += new ElapsedEventHandler(TimeProc);
MyTimer.Enabled = true;
Console.ReadLine();
}
}
2) 第二种方式是关于 SynchronizingObject,但它仅对 Windows 窗体应用程序有价值或需要额外开发代码来实现将实现 ISynchronizeInvoke 接口的对象。有关此方式的更多信息,您可以找到here
所以,现在我更喜欢第一个解决方案。
【问题讨论】:
-
计时器没有问题...这种情况到处都有。将 Elapsed 事件排队实际上很好。如果这是一个硬件中断,你会破坏你的间隔并且你无法恢复。
-
如果数据应该只处理一次,那么为什么要重复计时器,或者您的意思是每 X 次最多一次?
-
@Chris 在我的情况下,另一个应用程序将一些数据保存到数据库中,我的应用程序应该读取并处理它。
标签: c# .net vb.net multithreading timer