System.Timers.Timer против System.Threading.Timer

В последнее время я проверял некоторые из возможных таймеров, и Threading.Timer и Timers.Timer - те, которые мне нужны (так как они поддерживают пул потоков).

Я делаю игру, и я планирую использовать все типы событий, с разными интервалами и т. Д.

Что будет лучшим?

9 ответов

Решение

Эта статья предлагает довольно полное объяснение:

" Сравнение классов таймеров в библиотеке классов.NET Framework" - также доступно в виде файла.chm

Конкретная разница заключается в том, что System.Timers.Timer ориентирован на многопоточные приложения и поэтому является потокобезопасным благодаря SynchronizationObject собственность, тогда как System.Threading.Timer по иронии судьбы не является потокобезопасным из коробки.

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

System.Threading.Timer простой таймер. Он вызывает вас обратно в поток пула потоков (из рабочего пула).

System.Timers.Timer это System.ComponentModel.Component это оборачивает System.Threading.Timerи предоставляет некоторые дополнительные функции, используемые для диспетчеризации в определенном потоке.

System.Windows.Forms.Timer вместо этого оборачивает собственный HWND только для сообщений и использует оконные таймеры для вызова событий в этом цикле сообщений HWND.

Если ваше приложение не имеет пользовательского интерфейса и вам нужен максимально легкий и универсальный таймер.Net, возможный (потому что вы счастливы, выясняя свою собственную многопоточность / диспетчеризацию), тогда System.Threading.Timer так хорошо, как он получает в рамках.

Я не до конца понимаю, с чем предполагаемые проблемы с безопасностью потоков System.Threading.Timer являются. Возможно, это то же самое, что задано в этом вопросе: потокобезопасность System.Timers.Timer против System.Threading.Timer, или, возможно, каждый просто означает, что:

  1. Легко писать условия гонки, когда вы используете таймеры. Например, смотрите этот вопрос: Таймер (System.Threading) поток безопасности

  2. повторный вход уведомлений таймера, когда ваше событие таймера может вызвать и перезвонить вам во второй раз, прежде чем вы закончите обработку первого события. Например, посмотрите на этот вопрос: Потоковое выполнение с использованием System.Threading.Timer и Monitor

В своей книге "CLR Via C#" Джефф Ритчер не рекомендует использовать System.Timers.Timerэтот таймер получен из System.ComponentModel.Component, что позволяет использовать его в области проектирования Visual Studio. Так что это было бы полезно, только если вы хотите, чтобы таймер на поверхности дизайна.

Он предпочитает использовать System.Threading.Timer для фоновых задач в потоке пула потоков.

Информация от Microsoft об этом (см. Замечания по MSDN):

  • System.Timers.Timer, который запускает событие и выполняет код в одном или нескольких приемниках событий через равные промежутки времени. Класс предназначен для использования в качестве серверного или сервисного компонента в многопоточной среде; он не имеет пользовательского интерфейса и не виден во время выполнения.
  • System.Threading.Timer, который регулярно выполняет один метод обратного вызова в потоке пула потоков. Метод обратного вызова определяется, когда создается таймер, и его нельзя изменить. Как и класс System.Timers.Timer, этот класс предназначен для использования в качестве серверного или служебного компонента в многопоточной среде; он не имеет пользовательского интерфейса и не виден во время выполнения.
  • System.Windows.Forms.Timer (только.NET Framework), компонент Windows Forms, который запускает событие и выполняет код в одном или нескольких приемниках событий через равные промежутки времени. Компонент не имеет пользовательского интерфейса и предназначен для использования в однопоточной среде; он выполняется в потоке пользовательского интерфейса.
  • System.Web.UI.Timer (только.NET Framework), компонент ASP.NET, который выполняет асинхронную или синхронную обратную передачу веб-страниц с регулярным интервалом.

Интересно отметить, что System.Timers.Timer устарел в.NET Core 1.0, но был снова реализован в.NET Core 2.0 (/ .NET Standard 2.0). Цель.NET Standard 2.0 состояла в том, чтобы было как можно проще переключиться с.NET Framework, что, вероятно, стало причиной его возвращения.

Когда он устарел, рекомендуется использовать надстройку анализатора переносимости.NET Visual Studio System.Threading.Timer вместо.

Похоже, что Microsoft одобряет System.Threading.Timer до System.Timers.Timer,

РЕДАКТИРОВАТЬ ПРИМЕЧАНИЕ 2018-11-15: я передаю свой ответ, так как старая информация о.NET Core 1.0 больше не действительна.

Одно важное отличие, не упомянутое выше, которое может вас поймать, заключается в том, что System.Timers.Timer молча глотает исключения, тогда как System.Threading.Timer не делает.

Например:

var timer = new System.Timers.Timer { AutoReset = false };
timer.Elapsed += (sender, args) =>
{
    var z = 0;
    var i = 1 / z;
};
timer.Start();

против

var timer = new System.Threading.Timer(x =>
{
    var z = 0;
    var i = 1 / z;
}, null, 0, Timeout.Infinite);

Я нашел краткое сравнение с MSDN

Библиотека классов.NET Framework включает четыре класса с именем Timer, каждый из которых предлагает различные функции:

System.Timers.Timer, который запускает событие и выполняет код в одном или нескольких приемниках событий через равные промежутки времени. Класс предназначен для использования в качестве серверного или сервисного компонента в многопоточной среде; он не имеет пользовательского интерфейса и не виден во время выполнения.

System.Threading.Timer, который выполняет один метод обратного вызова в потоке пула потоков через равные промежутки времени. Метод обратного вызова определяется, когда создается таймер, и его нельзя изменить. Как и класс System.Timers.Timer, этот класс предназначен для использования в качестве серверного или служебного компонента в многопоточной среде; он не имеет пользовательского интерфейса и не виден во время выполнения.

System.Windows.Forms.Timerкомпонент Windows Forms, который запускает событие и выполняет код в одном или нескольких приемниках событий через равные промежутки времени. Компонент не имеет пользовательского интерфейса и предназначен для использования в однопоточной среде.

System.Web.UI.Timerкомпонент ASP.NET, который выполняет асинхронную или синхронную обратную передачу веб-страниц с регулярным интервалом.

Из MSDN: System.Threading.Timer это простой, легкий таймер, который использует методы обратного вызова и обслуживается потоками пула потоков. Это не рекомендуется для использования с Windows Forms, потому что его обратные вызовы не происходят в потоке пользовательского интерфейса. System.Windows.Forms.Timer это лучший выбор для использования с Windows Forms. Для серверной функциональности таймера, вы можете рассмотреть возможность использования System.Timers.Timer, который вызывает события и имеет дополнительные функции.

Источник

Как уже упоминалось в ссылке на MS Docs, одно из основных различий между и заключается в том, что выполняется один метод обратного вызова, определенный один раз , когда он реагирует на события, поэтому поддерживает несколько подписчиков, которых также можно удалить.

Как также упоминалось выше, System.Timers.Timerиспользует System.Threading.Timerвнутренне, например, Enable=false размещает внутренний таймер и повторно создает его на Enable=true/Start(): https://source.dot.net/#System.ComponentModel.TypeConverter/System/Timers/Timer.cs

Два класса функционально эквивалентны, за исключением того, что System.Timers.Timer имеет возможность вызывать все свои обратные вызовы истечения таймера через ISynchronizeInvoke, устанавливая SynchronizingObject. В противном случае оба таймера вызывают обратные вызовы с истечением срока действия в потоках пула потоков.

Когда вы перетаскиваете System.Timers.Timer на поверхности разработки Windows Forms Visual Studio устанавливает SynchronizingObject для объекта формы, что приводит к вызову всех обратных вызовов с истечением срока действия в потоке пользовательского интерфейса.

Другие вопросы по тегам