intVal = Interlocked.Increment(ref intVal);

В дополнение к методам Increment() и Decrement() тип Interlocked позволяет атомарно присваивать числовые и объектные данные. Например, чтобы присвоить переменной-члену значение 83, можно обойтись без явного оператора lock (или явной логики Monitor) и применить метод Interlock.Exchange():

Interlocked.Exchange(ref myInt, 83);

Наконец, если необходимо проверить два значения на предмет равенства и изменить элемент сравнения в безопасной к потокам манере, тогда допускается использовать метод Interlocked.CompareExchange():

public void CompareAndExchange()

{

  // Если значение i равно 83, то изменить его на 99.

  Interlocked.CompareExchange(ref i, 99, 83);

}

<p id="AutBody_Root553">Программирование с использованием обратных вызовов Timer</p>

Многие приложения нуждаются в вызове специфического метода через регулярные интервалы времени. Например, в приложении может существовать необходимость в отображении текущего времени внутри панели состояния с помощью определенной вспомогательной функции. Или, скажем, нужно, чтобы приложение эпизодически вызывало вспомогательную функцию, выполняющую некритичные фоновые задачи, такие как проверка поступления новых сообщений электронной почты. В ситуациях подобного рода можно применять тип System.Threading.Timer в сочетании со связанным делегатом по имени TimerCallback.

В целях иллюстрации предположим, что у вас есть проект консольного приложения (TimerApp), которое будет выводить текущее время каждую секунду до тех пор, пока пользователь не нажмет клавишу <Enter> для прекращения работы приложения. Первый очевидный шаг — написание метода, который будет вызываться типом Timer (не забудьте импортировать в свой файл кода пространство имен System.Threading):

using System;

using System.Threading;

Console.WriteLine("***** Working with Timer type *****\n");

Console.ReadLine();

static void PrintTime(object state)

{

  Console.WriteLine("Time is: {0}",

    DateTime.Now.ToLongTimeString());

}

Обратите внимание, что метод PrintTime() принимает единственный параметр типа System.Object и возвращает void. Это обязательно, потому что делегат TimerCallback может вызывать только методы, которые соответствуют такой сигнатуре. Значение, передаваемое целевому методу делегата TimerCallback, может быть объектом любого типа (в случае примера с электронной почтой параметр может представлять имя сервера Microsoft Exchange Server для взаимодействия в течение процесса). Также обратите внимание, что поскольку параметр на самом деле является экземпляром типа System.Object, в нем можно передавать несколько аргументов, используя System.Array или специальный класс либо структуру.

Следующий шаг связан с конфигурированием экземпляра делегата TimerCallback и передачей его объекту Timer. В дополнение к настройке делегата TimerCallback конструктор Timer позволяет указывать необязательный информационный параметр для передачи целевому методу делегата (определенный как System.Object), интервал вызова метода и период ожидания (в миллисекундах), который должен истечь перед первым вызовом. Вот пример:

Console.WriteLine("***** Working with Timer type *****\n");

// Создать делегат для типа Timer.

TimerCallback timeCB = new TimerCallback(PrintTime);

// Установить параметры таймера.

Timer t = new Timer(

  timeCB,     // Объект делегата TimerCallback.

  null,       // Информация для передачи в вызванный метод.

              // (null, если информация отсутствует).

  0,          // Период ожидания перед запуском (в миллисекундах).

  1000);      // Интервал между вызовами (в миллисекундах).

Console.WriteLine("Hit Enter key to terminate...");

Console.ReadLine();

В этом случае метод PrintTime() вызывается приблизительно каждую секунду и не получает никакой дополнительной информации. Ниже показан вывод примера:

Перейти на страницу:

Похожие книги