|
|
Опубликовано 12.10.2017 13:12:51
|
|
|

О классе таймеров в C# В C# есть три класса таймеров
1. Определить в System.Windows.Forms
2. Определено в классе System.Threading.Timer
3. Определено в классе System.Timers.Timer
System.Windows.Forms.Timer применяется к WinForm, реализуется через механизм сообщений Windows, аналогично контролю таймера в VB или Delphi, и реализуется внутренне с помощью API SetTimer. Её основной недостаток — неточное время, и должен быть цикл сообщений, который недоступен консольному приложению.
System.Timers.Timer очень похож на System.Threading.Timer, реализован через .NET Thread Pool, лёгкий, точный тайминг и без особых требований к приложениям и сообщениям. System.Timers.Timer также может быть применён к WinForm, полностью заменяя вышеуказанное управление таймером. Их недостаток в том, что они не поддерживают прямое перетаскивание и требуют ручного кодирования.
Пример:
Используйте класс System.Timers.Timer
System.Timers.Timer t = новый System.Timers.Timer(10000); Заработайте класс таймера и установите интервал на 10 000 миллисекунд.
t.Elapsed += новый System.Timers.ElapsedEventHandler(theout); Выполнять события по мере достижения времени;
t.AutoReset = true; Установите, выполнять ли один раз (false) или всё время (true);
t.Enabled = true; выполнять ли событие System.Timers.Timer.Elapsed;
public void theout(object source, System.Timers.ElapsedEventArgs e)
{
MessageBox.Show («Хорошо!»);
}
Экспериментальный анализ сходств и различий между использованием трёх таймеров в C#
http://dotnet.chinaitlab.com/CSharp/737740.html
В C# доступны три типа таймеров:
1. Стандартный таймер на базе Windows (System.Windows.Forms.Timer)
2. Серверный таймер (System.Timers.Timer)
3. Таймер потоков (System.Threading.Timer)
Давайте рассмотрим несколько небольших экспериментов, чтобы проанализировать сходства и различия между тремя таймерами, особенно часть, связанную с потоками.
Скриншот экспериментального примера:
1. Стандартный таймер на базе Windows (System.Windows.Forms.Timer)
Первое, что стоит отметить — Windows Timer предназначен для однопоточных сред
Этот таймер присутствует в продукте с версии Visual Basic 1.0 и остался практически без изменений
Этот таймер самый простой в использовании, просто перетащите управление таймером из инструментария в форму и задайте такие свойства, как события и интервалы
Экспериментальные результаты также полностью соответствуют характеристикам однопоточной резьбы:
1. При запуске этого таймера идентификатор дочернего потока отображается в списке идентификаторов дочерних потоков ниже, и он совпадает с основным идентификатором потока
private void formsTimer_Tick(object sender, EventArgs e)
{
i++;
lblSubThread.Text += "Выполнение субпотока, идентификатор потока:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + "\r\n";
}
2. Когда основной поток приостановлен на 5 секунд, дочерний поток приостанавливает выполнение, а если ранее приостановленный дочерний поток не будет выполнен через 5 секунд, следующий дочерний поток выполняется напрямую (то есть он выведет несколько строк значений).
System.Threading.Thread.Sleep (5000);
3. Пауза событий дочернего процесса на 5 секунд приведёт к тому, что главное окно станет неотзывчивым на 5 секунд
4. Определите статическую переменную потока:
[Шум нити]
приватный статический int i = 0;
Добавьте по одной к каждому событию подпотока, а затем нажмите на значение статической переменной потока, чтобы получить увеличенное значение i
2. Серверный таймер (System.Timers.Timer)
System.Timers.Timer не зависит от форм, пробуждает потоки из пула потоков и является обновлённой версией традиционного таймера, оптимизированной для работы в серверной среде
В наборе инструментов VS2005 нет готовых органов управления, и для использования этого таймера необходимо вручную кодировать
Есть два способа её использовать,
1. Прикрепить форму через свойство SynchronizingObject
System.Timers.Timer timersTimer = новый System.Timers.Timer();
timersTimer.Enabled = false;
таймерыTimer.Interval = 100;
timersTimer.Elapsed += new System.Timers.ElapsedEventHandler(timersTimer_Elapsed);
timersTimer.SynchronizingObject = это;
Таким образом, эксперимент работает почти так же, как стандартный таймер на базе Windows, за исключением того, что во втором эксперименте выше, хотя выполнение подпотока тоже будет приостановлено, но через 5 секунд все ранее поставленные в очередь задачи будут выполнены (то есть несколько строк значения не будут пропущены).
2. Не используйте свойство SynchronizingObject
Этот метод многопоточный, то есть начальный дочерний поток и основная форма не находятся на одном потоке. Однако есть и проблема: поскольку подпоток является отдельным потоком, элементы управления в форме недоступны, а доступны только через прокси:
delegate void SetTextCallback (текст строки);
Источник: (http://blog.sina.com.cn/s/blog_5aeeb8200100bhc4.html) - (Поворот) Сравнение трёх таймерных объектов в блоге C#_dash_Sina
。
。
void timersTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//使用代理
текст строки = "исполнение дочернего потока, идентификатор потока:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + "\r\n";
SetTextCallback d = новый SetTextCallback(SetText);
Вот именно. Invoke(d, new object[] { text });
i++;
}
private void SetText (текст строки)
{
lblSubThread.Text += текст;
}
Таким образом, мы снова получим следующие результаты эксперимента:
1. При запуске этого таймера ID дочернего потока отображается в списке идентификаторов дочерних потоков ниже и отличается от основного идентификатора потока
2. Когда вы кликаете на основной поток для паузы на 5 секунд, подпоток продолжит выполнение (он может быть не виден на интерфейсе, но легко увидеть, выведя файл в подпотоке)
3. Пауза событий дочернего процесса на 5 секунд не приведёт к тому, что главное окно станет неотзывчивым
4. Добавляйте одну в статическую переменную потока каждый раз в событии подпотока, а затем нажмите, стоит ли статическая переменная потока 0 или 0 (она не изменит статическую переменную потока в главном окне).
3. Таймер потоков (System.Threading.Timer)
Таймеры потоков также не зависят от форм, это простые, лёгкие таймеры, использующие методы обратного вызова вместо событий, и работают на потоках пула потоков.
Таймеры потоков полезны в ситуациях, когда сообщения не отправляются по потокам.
Вот как им пользоваться:
System.Threading.Timer threadTimer;
public void ThreadMethod(состояние объекта)
{
//使用代理
текст строки = "исполнение дочернего потока, идентификатор потока:" + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + "\r\n";
SetTextCallback d = новый SetTextCallback(SetText);
Вот именно. Invoke(d, new object[] { text });
i++;
}
private void Form1_Load(object sender, EventArgs e)
{
threadTimer = новый System.Threading.Timer (new System.Threading.TimerCallback(ThreadMethod), null, -1, -1);
}
Код паузы:
threadTimer.Change(-1, -1);
Эффект эксперимента совпадает со вторым способом серверного таймера (System.Timers.Timer).
Конечно, конкретные методы использования и принципы различаются, самое важное — что этот метод использует агентный метод вместо метода событий и может выполняться отдельно, не полагаясь на формы и компоненты
Ниже приведена таблица, обобщённая иностранцами (разница между тремя методами):
Feature descrip{filter}tion System.Timers.Timer System.Threading.Timer System.Windows.Forms.Timer
Поддержка добавления и удаления слушателей после запуска таймера. Да, нет, да.
Поддерживает обратные вызовы в теме пользовательского интерфейса Yes No Yes
Обратные звонки из потоков, полученных из пула потоков. Да, да, нет.
Поддерживает перетаскивание в Windows Forms Designer Yes Нет Да
Подходит для работы в серверной многопоточной среде Да Да Нет
Включает поддержку передачи произвольного состояния от инициализации таймера к обратному вызову. Нет, да, нет
Реализует IDisposable Да
Поддерживает одноразовые обратные звонки, а также периодические повторяющиеся вызовы Да Да
Доступно через границы доменов приложений Да Да Да
Поддерживает IComponent — можно разместить в IContainer Да Нет Да |
Предыдущий:c# Дегруппировка выражений Lamda, чтобы принять минимальное значениеСледующий:Linq: Никогда не используйте Count() > 0, чтобы определить, что множество не пусто
|