Таймеры C# протекают на отдельном потоке?

Я предпочитаю команда nohup. Сообщение в блоге говорит, что существуют лучшие пути, но я не думаю, что они достаточно лучше.

86
задан user113164 16 September 2009 в 22:36
поделиться

4 ответа

Для System.Timers.Timer :

См. ответ Брайана Гидеона ниже

Для System.Threading.Timer :

В документации MSDN по таймерам указано:

Класс System.Threading.Timer делает обратные вызовы в потоке ThreadPool и вообще не использует модель событий.

Так что действительно таймер истекает в другом потоке.

56
ответ дан 24 November 2019 в 07:56
поделиться

It depends. The System.Timers.Timer has two modes of operation.

If SynchronizingObject is set to an ISynchronizeInvoke instance then the Elapsed event will execute on the thread hosting the synchronizing object. Usually these ISynchronizeInvoke instances are none other than plain old Control and Form instances that we are all familiar with. So in that case the Elapsed event is invoked on the UI thread and it behaves similar to the System.Windows.Forms.Timer. Otherwise, it really depends on the specific ISynchronizeInvoke instance that was used.

If SynchronizingObject is null then the Elapsed event is invoked on a ThreadPool thread and it behaves similar to the System.Threading.Timer. In fact, it actually uses a System.Threading.Timer behind the scenes and does the marshaling operation after it receives the timer callback if needed.

181
ответ дан 24 November 2019 в 07:56
поделиться

Каждое прошедшее событие будет запускаться в том же потоке, если предыдущее Elapsed еще не запущено.

Таким образом, он обрабатывает коллизию за вас

попробуйте поместить это в консоль

static void Main(string[] args)
{
    Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
    var timer = new Timer(1000);
    timer.Elapsed += timer_Elapsed;
    timer.Start();
    Console.ReadLine();
}

static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    Thread.Sleep(2000);
    Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
}

вы получит что-то вроде этого

10
6
12
6
12

, где 10 - это вызывающий поток, а 6 и 12 запускаются из истекшего события bg. Если удалить Thread.Sleep (2000); вы получите что-то вроде этого

10
6
6
6
6

Так как коллизий нет.

Но это все равно оставляет вам проблему. если вы запускаете событие каждые 5 секунд и для редактирования требуется 10 секунд, вам нужна блокировка, чтобы пропустить некоторые изменения.

21
ответ дан 24 November 2019 в 07:56
поделиться

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

static void timer_Elapsed(object sender, ElapsedEventArgs e)    
{     
   try
   {
      timer.Stop(); 
      Thread.Sleep(2000);        
      Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);    
   }
   finally
   {
     timer.Start();
   }
}
12
ответ дан 24 November 2019 в 07:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: