Ваш ProcessMessage
никогда не проверяет, сигнализируется ли resetEvent
- он просто работает независимо от
Я пишу здесь, как это исправить. Однако это не идеальный способ делать то, что вы хотите. Смотрите в нижней части моего ответа для этого.
У вас есть звонок на autoEvent.WaitOne()
в неправильном месте; это должно быть в начале метода ProcessMessage
.
AutoResetEvent autoEvent = (AutoResetEvent)stateObject;
autoEvent.WaitOne();
Trace.Write("Starting ProcessQueue");
SmtpClient smtp = new SmtpClient("winprev-01");
foreach (MessageQueue message in AllUnprocessed){
Вам также следует использовать перегрузку, которая принимает значение времени ожидания (int или timespan) и возвращает bool
Если метод возвращает true
, это означает, что ему было сообщено, поэтому вы можете продолжить. Если время истекло (потому что еще одна итерация все еще выполняется), вы должны просто вернуться и не пытаться запустить код снова.
Если вы не используете такую перегрузку, то, что вы делаете, ничем не отличается от упаковки кода метода ProcessMessage в критическую секцию (например, lock()
в глобальном var) - дополнительные потоки будут блокироваться, а затем без необходимости бежать.
AutoResetEvent autoEvent = (AutoResetEvent)stateObject;
//wait just one ms to see if it gets signaled; returns false if not
if(autoEvent.WaitOne(1)){
Trace.Write("Starting ProcessQueue");
SmtpClient smtp = new SmtpClient("winprev-01");
foreach (MessageQueue message in AllUnprocessed){
Обратите внимание, что на самом деле *ResetEvent
здесь не идеален. Вы действительно просто хотите проверить, запущен ли экземпляр, и прервать работу, если это так. ResetEvent
на самом деле не созданы для этого ... но я все равно хотел ответить на вопрос об использовании ResetEvent.
Что, вероятно, будет работать лучше, это просто выключить таймер при вызове обратного вызова, а затем перезапустить его, когда вы закончите. Таким образом, невозможно повторно ввести этот код, пока он еще работает.
Вы, безусловно, должны будете обернуть весь код в методе обратного вызова в try
/ finally
, чтобы вы всегда перезапускали таймер после.