标准的System.Timers.Timer行为存在问题。计时器引发耗时间隔有一定间隔的事件。但是,当经过的事件处理程序中的执行时间超过计时器间隔时,线程池便开始对事件处理进行排队。就我而言,这是一个问题。这是因为使用我的Elapsed事件处理程序,我从数据库中获取了一些数据并对其进行了处理,最后将结果保存回数据库中。但是数据处理应仅提供一次。因此,有没有一种方法可以防止System.Timers.Timer的经过事件排队。

作为此问题的说明,您可以考虑下一个测试程序:

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接口(interface)的对象有用。有关此方法的更多信息,您可以找到here

所以,现在我将首选第一个解决方案。

最佳答案

在这种情况下,我通常要做的是在Elapsed处理程序的开始处停止计时器,然后在结尾处再次启动它。这样,您一次只处理一个刻度。

更新:

通过MSDN链接,我认为它们的意思是您可以设置自己的标志(但仍然会出现滴答声),但也应采取线程安全措施。

10-06 13:51