Как предотвратить постановку System.Timers.Timer в очередь для выполнения в пуле потоков?

Возникла проблема со стандартным поведением System.Timers.Timer. Таймер вызывает событие Elapsed с некоторым интервалом. Но когда время выполнения внутри обработчика событий Elapsed превышает интервал таймера, пул потоков начинает обработку событий в очереди. В моем случае это проблема. Это связано с тем, что с помощью обработчика событий 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  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 # против потока в службе

И имеет код, подобный здесь, относительно упомянутого выше примера:

    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  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 form или требует дополнительной разработки код для реализации объекта, который реализует интерфейс ISynchronizeInvoke. Подробнее об этом способе вы можете найти здесь

Итак, пока я предпочитаю первое решение.

12
задан Community 23 May 2017 в 12:32
поделиться