2016-11-21 2 views
0

Я использую System.Timers.Timer с функцией, установленной в Истекшее. 'aTimer.Elapsed + = OnTimedEvent` установлен для периодического запуска в обычное время. Предположим, что это происходит каждые 5 секунд.Таймер (вызов функции с истекшим временем несколько раз)

Что произойдет, если по какой-либо причине обработка OnTimedEvent последней более чем 5 секунд.

В соответствии с документацией * событие может быть снова поднято на другой поток ThreadPool. В этой ситуации обработчик события должен быть реентерабельным. *

Хотя я понимаю, что это так теоретически, может кто-нибудь объяснить это мне в более простых и практических выражениях?

Если это помогает в моем onTimedEvent, я пытаюсь читать из NetworkStream.

+0

Попробуйте сами. Чак 'Thread.Sleep (7000)' внутри 'OnTimedEvent'. – Rob

+0

Обязательно установите для параметра [свойство AutoReset] (https://msdn.microsoft.com/en-us/library/system.timers.timer.autoreset (v = vs.110) .aspx) значение * false *. Код примера в статье немного сломан, вызовите Start() в конце обработчика событий Elapsed, чтобы снова установить отметку таймера. И в значительной степени отдайте предпочтение try/catch/finally в обработчике событий. –

ответ

1

Простыми словами это означает: OnTimedEvent должен поддерживать несколько потоков, проходящих через него в одно и то же время. Зачем? Поскольку, пока ваш метод выполняется, если вы не остановите таймер, он снова выстрелится через 5 секунд. Но на этот раз он запустится в другой поток, так как первый поток занят выполнением первого вызова. Поэтому второй поток войдет в метод. На данный момент, если OnTimedEvent не является потокобезопасным, могут произойти плохие вещи.

Вы можете google больше о поддержке нескольких потоков, и вы сможете найти много информации.

Большую часть времени люди останавливают таймер во время выполнения метода, а затем перезапускают его в конце метода. Но это зависит от ваших требований и от того, что вы делаете.

Вот пример NON метода возвратного:

static int sum = 0; 

int increment(int i) { 
    sum += i; 
    return sum; 
} 

Это не реентрантные, потому что если T1 находится внутри метода его выполнения и добавляет 1 к сумме, сумма будет 1. Если прерывается, что означает, что контроль выполнения выполняется в этой точке и задан для T2, когда T2 приходит, значение суммы не будет равно 0, но 1. T2 добавит 1 к сумме и возвращает 2. Когда T1 вернется, он будет продолжать, откуда оставлено, т. е. уже сделано добавление, так что оно просто вернет 1. Таким образом, 2 потока остались с разным результатом: T1 с 1, T2 с 2. Поэтому метод не является повторным.

Чтобы сделать это Реентрантным, мы просто делаем это:

int increment(int sum, int i) 
{ 
    return sum + i; 
} 

Теперь каждый поток будет возвращать тот же ответ, даже если они оставляют в середине выполнения метода, так как все переменные на стек и не разделяется потоками (каждый поток будет иметь свою собственную копию переменных).

This Ответ на сообщение содержит отличную информацию и объяснение, если вы хотите узнать больше.

Смежные вопросы