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