2015-06-19 2 views
0

У меня вопрос о таймере. Выполняет ли время выполнения обратного вызова время интервала времени? Я имею в виду, например, у меня есть таймер, срабатывающий каждые 15 секунд, и он выполняет функцию обратного вызова, которая длится примерно 3 секунды. Когда в следующий раз будет срабатывать таймер? Через 18 секунд (после завершения обратного вызова) или через 15 секунд (без ожидания обратного вызова) ??? Заранее благодаренSystem.Threading.Timer ... Время следующего пожара?

+1

Таймер не имеет никакого отношения к его обратному вызову. Он будет срабатывать через 15 секунд –

+0

, поэтому обратный вызов будет выполнен в другом потоке? –

+1

http://blog.stackoverflow.com/2011/12/dont-be-afraid-to-use-the-science/ –

ответ

3

Он будет срабатывать каждые 15 секунд независимо от времени выполнения обратного вызова. Если вы хотите включить время выполнения обратного вызова, вы можете приостановить и перезапустить таймер в обратном вызове следующим образом;

На старте:

someTimer.Change(Timeout.Infinite, Timeout.Infinite)

.. и в конце концов, изменить его обратно с тем же методом:

someTimer.Change(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15))

+1

Вам не нужно менять таймер в начале, просто не указывайте период, чтобы таймер срабатывал только один раз. Таким образом, вызов «Change» на конце обратного вызова сбросит таймер –

0

Он будет срабатывать каждые 15 секунд. Любые задержки с помощью обратного вызова не влияют на таймер. Обратный вызов выполняется в отдельном потоке ThreadPool. От

Метод не выполняется в потоке, который создал таймер; он выполняется в потоке ThreadPool, поставляемом системой.

Если вы хотите, чтобы занять время обработки во внимание, вы должны управлять таймер самостоятельно - запустить таймер одного пожара и сбросить его изнутри обратного вызова, например:

TimerCallback tcb = MyCallBack; 
//Start the timer once after 15 secs 
_timer=new Timer(tcb,null,TimeSpan.FromSeconds(15),TimeSpan.Infinite); 

... 
void MyCallBack(Object stateInfo) 
{ 
    .... 
    //Reset the timer 
    _timer.Change(TimeSpan.FromSeconds(15),TimeSpan.Infinite); 
} 

проще и чище использовать async/await, чтобы ждать X секунд после каждого асинхронного выполнения. Например, следующий код будет выполнен метод 15 секунд после последнего выполнения:

while(...) 
{ 
    await Task.Delay(TimeSpan.FromSeconds(15)); 
    var response=await Task.Run(()=>someMethod()); 
    ... 
} 

или, если вы хотите выполнить код, который уже асинхронный

while(...) 
{ 
    await Task.Delay(TimeSpan.FromSeconds(15)); 
    await myHttpClient.GetStringAsync(someURL); 
} 

Под капотом Task.Delay создает однократного таймера и завершается, когда таймер заканчивается. Это почти то же самое, что вы сделали бы вручную.

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