Эндрю Троелсен - ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
- Название:ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2007
- Город:Москва • Санкт-Петербург • Киев
- ISBN:ISBN 5-8459-1124-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Эндрю Троелсен - ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание краткое содержание
В этой книге содержится описание базовых принципов функционирования платформы .NET, системы типов .NET и различных инструментальных средств разработки, используемых при создании приложений .NET. Представлены базовые возможности языка программирования C# 2005, включая новые синтаксические конструкции, появившиеся с выходом .NET 2.0, а также синтаксис и семантика языка CIL. В книге рассматривается формат сборок .NET, библиотеки базовых классов .NET. файловый ввод-вывод, возможности удаленного доступа, конструкция приложений Windows Forms, доступ к базам данных с помощью ADO.NET, создание Web-приложений ASP.NET и Web-служб XML. Книга содержит множество примеров программного кода, призванного помочь читателю в освоении предлагаемого материала. Программный код примеров можно загрузить с Web-сайта издательства.
ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
public void AddOne() {
lock(this) {
intVal++;
}
}
можно предложить более простой программный код, в котором используется статический метод Interlocked.Increment(). Просто передайте переменную для приращения по ссылке. Обратите внимание на то, что метод Increment() не только изменяет значение поступающего параметра, но и возвращает новое значение.
public void AddOne() {
int newVal = Interlocked.Increment(ref intVal);
}
В дополнение к Increment() и Decrement() тип Interlocked позволяет атомарно присваивать числовые и объектные данные. Например, если вы хотите присвоить члену-переменной значение 83, вы можете избежать необходимости явного использования оператора lock (или явного применения логики Monitor), если используете метод Interlocked.Exchange().
public void SafeAssignment() {
Interlocked.Exchange(ref myInt, 83);
}
Наконец, при проверке двух значений на равенство, чтобы обеспечить потоковую безопасность элементу сравнения, можете использовать метод Interlocked.CompareExchange(), как показано ниже.
public void CompareAndExchange() {
// Если значением i является 83, изменить его на 99.
Interlocked. CompareExchange(ref i, 99, 83);
}
Синхронизация с помощью атрибута [Synchronization]
Последним из рассмотренных здесь примитивов синхронизации будет атрибут [Synchronization], который определяется в пространстве имен System.Runtime.Remoting.Contexts. Этот атрибут уровня класса для безопасности потока эффективно блокирует весь программный код членов экземпляра. Когда среда CLR размещает объект, имеющий атрибут [Synchronization], она помещает этот объект в рамки синхронизированного контекста. Вы должны помнить из главы 13, что объекты, которые не должны покидать контекстные границы, являются производными от ContextBoundObject. Поэтому, чтобы сделать тип класса Printer устойчивым в отношении потоков (без добавления программного кода защиты потоков вручную), следует изменить соответствующее определение так.
using System.Runtime.Remoting.Contexts;
...
// Все методы Printer теперь потокоустойчивы!
[Synchronization]
public class Printer: СontextBoundObject {
public void PrintNumbers() {
…
}
}
Этот подход можно назвать способом создания потокоустойчивого программного кода для ленивых, поскольку здесь не требуется выяснять, какие фрагменты типа могут испытывать влияние внешних потоков. Главным недостатком этого подхода является то, что даже если какой-то метод и не испытывает влияния внешних потоков, среда CLR все равно блокирует обращение к этому методу. Очевидно, это может ухудшить общие характеристики функционирования типа, так что используйте указанный подход с осторожностью.
Итак, мы с вами обсудили целый ряд подходов к решению вопроса синхронизированного доступа к общим блокам данных. Будьте уверены, в пространстве имен System.Threading есть и другие типы, которые я настоятельно рекомендую вам постепенно исследовать. В завершение этой главы, посвященной программированию потоков, давайте рассмотрим три: дополнительных типа: TimerCallback, Timer и ThreadPool.
Программирование с помощью таймеров обратного вызова
Во многих приложениях возникает необходимость вызывать конкретный метод через регулярные промежутки времени. Например, в одном приложении может потребоваться отображение текущего времени в строке состояния с помощью некоторой вспомогательной функции. В другом приложении может понадобиться периодический вызов вспомогательной функции, выполняющей в фоновом режиме какие-то некритические задачи, например проверку поступления новых сообщений электронной почты. Для таких ситуаций можно использовать тип System. Threading.Timer в совокупности с соответствующим делегатом TimerCallback.
Для примера предположим, что нам нужно создать консольное приложение, которое ежесекундно выводит текущее время, пока пользователь не нажмет клавишу, завершающую выполнение этого приложения. Первым очевидным шагом здесь является создание метода, который будет вызываться типом Timer.
class TimePrinter {
static void PrintTime(object state) {
Console.WriteLine("Время: {0}", DateTime.Now.ToLongTimeString());
}
}
Этот метод имеет один параметр типа System.Object и возвращает void. Такая структура метода обязательна, поскольку делегат TimerCallback может вызывать только такие методы. Значение, передаваемое целевому методу делегата TimerCallback, может представлять любую информацию (так, в случае электронной почты это может быть имя сервера Microsoft Exchange, с которым требуется взаимодействие в ходе процесса). А так как параметр является типом System.Object, в действительности можно передать любое число аргументов, если использовать System.Array или пользовательский класс (структуру).
Следующим шагом является настройка экземпляра делегата TimerCallback и передача его объекту Timer. Кроме делегата TimerCallback, конструктор Timer позволяет указать дополнительную информацию (в виде System.Object) для передачи ее целевому объекту делегата, временной интервал опроса метода и время ожидания (в миллисекундах) до начала первого вызова, например:
static void Main(string[] args) {
Console.WriteLine("***** Работа с типом Timer *****\n");
// Создание делегата для типа Timer.
TimerCallback timeCB = new TimerCallback(PrintTime);
// Установка параметров таймера.
Timer t = new Timer(
timeCB, // Тип делегата TimerCallback.
null, // Информация для вызываемого метода или null.
0, // Время ожидания до старта.
1000); // Интервал между вызовами (в миллисекундах).
Console.WriteLine("Нажмите «Enter» для завершения работы…");
Console.ReadLine();
}
В данном случае метод PrintTime() будет вызываться примерно каждую секунду и методу не передается никакой дополнительной информации. Чтобы передать целевому объекту делегата какую-то информацию, замените значение null второго параметра конструктора подходящим значением (например, "Привет"). Следующая модификация метода PrintTime() использует переданное значение.
static void PrintTime(Object state) {
Console.WriteLine("Время: {0}, Параметр: {1}", DateTime.Now.ToLongTimeString(), state.ToString());
}
На рис. 14.11 показан соответствующий вывод.

Рис. 14.11. Таймеры за работой
Исходный код. Проект TimerApp размещен в подкаталоге, соответствующем главе 14.
Пул потоков CLR
Заключительной темой нашего обсуждения в этой плаве, посвященной потокам, будет пул потоков CLR. При асинхронном вызове типов с помощью делегатов (посредством метода BeginInvoke()) нельзя сказать, что среда CLR буквально создает совершенно новый поток. В целях эффективности метод BeginInvoke() делегата использует пул (динамическую область) рабочих потоков, поддерживаемых средой выполнения. Чтобы позволить вам взаимодействовать с этим пулом рабочих потоков, пространство имен System.Threading предлагает тип класса ThreadPool.
Читать дальшеИнтервал:
Закладка: