System.Timers.Timer vs System.Threading.Timer


565

Я перевірити деякі з можливих таймерів в останнім часом, а System.Threading.Timerй System.Timers.Timerті , які виглядають потрібного для мене (так як вони підтримують пул потоків).

Я роблю гру, і планую використовувати всі типи подій, з різними інтервалами тощо.

Який був би найкращий?

Відповіді:


363

Ця стаття пропонує досить вичерпне пояснення:

" Порівняння класів таймерів у бібліотеці .NET Framework Class " - також доступне у вигляді .chm-файлу

Здається, що особлива різниця System.Timers.Timerполягає в тому, що вона орієнтована на багатопотокові програми та, таким чином, є безпечною для потоків через свою SynchronizationObjectвластивість, тоді System.Threading.Timerяк за іронією долі не є безпечною для потоків поза коробкою.

Я не вірю, що між ними є різниця, оскільки це стосується того, наскільки невеликими можуть бути ваші інтервали.


69
Я думаю, що цей уривок є освічуючим: "На відміну від System.Windows.Forms.Timer, клас System.Timers.Timer за замовчуванням зателефонує вашому обробнику подій таймера на робочу нитку, отриману з пулу потоків загальної мови (CLR). . [...] Клас System.Timers.Timer пропонує простий спосіб вирішити цю дилему - він відкриває загальнодоступне властивість SynchroisingObject. Встановлення цього властивості на екземпляр Форми Windows (або елемента керування на Формі Windows) переконайтеся, що код у вашому обробці подій Elapsed працює на тій самій нитці, на якій був синхронізований об'єкт синхронізації. "
mico

7
Згідно з розділом потокобезпечна в Threading.Timer«пд.ш. статті MSDN , це абсолютно поточно- ...
Пітер

62
System.Threading.Timerнастільки ж "іронічно" не є безпечним для ниток, як System.Threading.Threadі нитки, отримані через пул. Тільки тому, що ці класи не тримають руку та керують використанням самого lockключового слова, це не означає, що ці класи не є безпечними для потоків. Ви також можете сказати, що System.Threading.Threadце не безпечно для ниток, тому що це точно так само.
Кірк Волл

8
Також інтервалом System.Timer.Timer може бути лише Int32 System.Threading.Timer інтервал може бути до Int64
Brent

11
Прикро, що ця дуже оманлива (в кращому випадку) відповідь прийнята і так високо підкреслена. Єдине матеріальне твердження у самій відповіді просто неправильне. SynchronizingObjectЧи не робить об'єкт таймера сам поточно-. Він просто гарантує, що ваш код для обробки події таймера викликається в певному потоці (якщо ви встановите це властивість відповідним чином). Сам об'єкт таймера не може бути безпечним для потоків, як це чітко зазначено в документації. З іншого боку, System.Threading.Timerоб'єкт є конкретно документований як потокобезпечна.
Пітер Дуніхо

169

System.Threading.Timer- звичайний таймер. Він повертає вас до потоку пулу потоків (з пулу робочих).

System.Timers.Timer- це System.ComponentModel.Componentте, що обгортає System.Threading.Timer, і надає деякі додаткові функції, що використовуються для диспетчеризації певної нитки.

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

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

Мені не зовсім зрозуміло, з чим System.Threading.Timerполягають нібито проблеми, що не стосуються безпеки. Можливо, це точно так само, як задають у цьому запитанні: безпека ниток у System.Timers.Timer vs System.Threading.Timer , або, можливо, всі просто означають, що:

  1. легко писати умови перегонів, коли ви використовуєте таймери. Наприклад, дивіться це питання: Безпека потоку в таймері (System.Threading)

  2. повторна застава сповіщень про таймер, де ваша подія таймера може викликати і передзвонити вам вдруге, перш ніж закінчити обробку першої події. Наприклад, дивіться це питання: безпечне виконання потоків за допомогою System.Threading.Timer і Monitor


Правда, System.Timers.Timerвикористовує System.Threading.Timerвнутрішньо. Див. Вихідний код .
стом

120

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

Він вважає за краще використовувати System.Threading.Timerдля фонових завдань на потоці пулу ниток.


36
Він може бути використаний на дизайнерській поверхні - це не означає, що він повинен бути, і немає згубних наслідків від цього не робити. Читаючи статтю в попередній відповіді на це запитання, Timers.Timer видається набагато кращим, ніж Threading.Timer.
Стівен Дрю

6
Що ж, що переважніше залежить від контексту, правда? Як я це розумію, System.Threading.Timer виконує зворотний виклик переданого номера на новому робочому потоці з ThreadPool. Я вважаю, що це також не є безпечним потоком. Щось має сенс. Тож теоретично вам не доведеться турбуватися про бурхливість розкручування власної робочої нитки, оскільки цей таймер зробить це за вас. Вигляд здається смішно корисним.
Фінстер

6
Використання System.Threading.Timerсхоже на використання пулу потоків або створення власного потоку. З Звичайно , ці класи не обробляють синхронізацію для вас - це ваша робота! Ні потік пулу потоків, ні ваша власна нитка, ні зворотний виклик таймера не оброблятимуть блокування - на якому об'єкті та яким способом та за яких обставин вам потрібно заблокувати, не потрібно добре оцінювати, і версія потоку таймера надає вам найбільшу гнучкість та зернистість.
Кірк Волл

2
-1 ця відповідь суб'єктивна або висловлюється з самого початку і не дає конкретної інформації, чому System.Threading.Timer віддається перевагою Джеффа Рітчера
Брайана Огдена

42

Інформація від 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 Portablebility Analyzer Visual StudioSystem.Threading.Timer .

Схоже, що Microsoft надає перевагу System.Threading.Timerраніше System.Timers.Timer.

РЕДАКЦІЯ ПРИМІТКА 2018-11-15: Я вручаю змінити свою відповідь, оскільки стара інформація про .NET Core 1.0 вже не була дійсною.



@Taegost, його використання також обмежене - див. MSDN msdn.microsoft.com/en-us/library/… та читайте зауваження щодо доступності платформи.
astrowalker

@astrowalker - Дякую за це, на той момент, коли я робив коментар, ця відповідь майже не мала деталей. Оскільки в ній є деталі, про які я розпитував, я видалив свій коментар.
Taegost

1
System.Timers.Timer тепер підтримується у .NET Standard 2.0 та .NET Core 2.0 та вище. docs.microsoft.com/en-us/dotnet/api/system.timers.timer (прокрутіть до кінця статті)
Лі Гріссом


39

Важлива відмінність, не згадана вище, яка може вас наздогнати, це те, що 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);

1
Я нещодавно потрапив у цю проблему з Timers.Timer, і це було дуже боляче ... Будь-які ідеї, як я можу переписати програму Threading.Timer? stackoverflow.com/questions/41618324/…
Тез Вінгфілд

7
У вихідному коді є порожній улов. Дивіться вихідний код
System.Timers.Timer

Омгш, чому MS-програмісти не здатні робити те саме, що дійсно так само?
xmedeko

2
Приклад не пояснює, як один ковтає винятки, а другий - ні. Чи може хтось, будь ласка, заповнити реквізити?
Sean

24

Я знайшов коротке порівняння від MSDN

Бібліотека .NET Framework Class включає чотири класи з назвою Таймер, кожен з яких пропонує різні функціональні можливості:

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

System.Threading.Timer, який виконує єдиний метод зворотного виклику на потоці пулу потоків через рівні проміжки часу. Метод зворотного виклику визначається, коли таймер інстанціюється і його неможливо змінити. Як і клас System.Timers.Timer, цей клас призначений для використання в якості сервера або сервісного компонента в багатопотоковому середовищі; він не має інтерфейсу користувача і не видно під час виконання.

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

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


1

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

Коли ви перетягуєте System.Timers.Timerна поверхню дизайну Windows Forms, Visual Studio встановлює SynchroisingObject на об’єкт форми, що викликає виклик усіх термінів виклику в потоці користувальницького інтерфейсу.


1

Від MSDN: System.Threading.Timerце простий, легкий таймер, який використовує методи зворотного виклику і обслуговується потоками пулу потоків. Не рекомендується використовувати з Windows Forms, оскільки його зворотні дзвінки не виникають у потоці користувальницького інтерфейсу. System.Windows.Forms.Timerє кращим вибором для використання з Windows Forms. Для функцій таймера на основі сервера ви можете скористатися System.Timers.Timer, що викликає події та додаткові функції.

Джерело

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.