Герберт Шилдт - C# 4.0: полное руководство
- Название:C# 4.0: полное руководство
- Автор:
- Жанр:
- Издательство:ООО И.Д. Вильямс
- Год:2011
- Город:Москва -- Киев
- ISBN:978-5-8459-1684-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Герберт Шилдт - C# 4.0: полное руководство краткое содержание
В этом полном руководстве по C# 4.0 - языку программирования, разработанному специально для среды .NET, - детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки.
Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.Введите сюда краткую аннотацию
C# 4.0: полное руководство - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Для того чтобы стало понятнее назначение методов Wait()
и Pulse()
, рассмотрим пример программы, имитирующей тиканье часов и отображающей этот процесс на экране словами "тик" и "так". Для этой цели в программе создается класс TickTock
, содержащий два следующих метода: Tick()
и Тоск()
. Метод Tick()
выводит на экран слово "тик", а метод Тоск()
— слово "так". Для запуска часов далее в программе создаются два потока: один из них вызывает метод Tick()
, а другой — метод Тоск()
. Преследуемая в данном случае цель состоит в том, чтобы оба потока выполнялись, поочередно выводя на экран слова "тик" и "так", из которых образуется повторяющийся ряд "тик-так", имитирующий ход часов.
//Использовать методы Wait() и Pulse() для иммитации
//тиканья часов
using System;
using System.Threading;
class TickTock {
object lockOn = new object();
public void Tick(bool running) {
lock(lockOn) {
if(!running) {
// остановить часы
Monitor.Pulse(lockOn); // уведомить любые ожидающие потоки
return;
}
Console.Write("тик ");
Monitor.Pulse(lockOn); // разрешить выполнение метода Tock()
Monitor.Wait(lockOn); // ожидать завершения метода Tock()
}
}
public void Tock(bool running) {
lock(lockOn) {
if(!running) { // остановить часы
Monitor.Pulse(lockOn); // уведомить любые ожидающие потоки
return;
}
Console.WriteLine("так");
Monitor.Pulse(lockOn); // разрешить выполнение метода Tick()
Monitor.Wait(lockOn); // ожидать завершения метода Tick()
}
}
}
class MyThread {
public Thread Thrd;
TickTock ttOb;
// Сконструировать новый поток.
public MyThread(string name, TickTock tt) {
Thrd = new Thread(this.Run);
ttOb = tt;
Thrd.Name = name;
Thrd.Start();
}
// Начать выполнение нового потока,
void Run() {
if(Thrd.Name == "Tick") {
for(int i=0; i<5; i++)
ttOb.Tick(true);
ttOb.Tick(false) ;
}
else {
for(int i=0; i<5; i++)
ttOb.Tock(true);
ttOb.Tock(false);
}
}
}
class TickingClock {
static void Main() {
TickTock tt = new TickTock();
MyThread mt1 = new MyThread("Tick", tt);
MyThread mt2 = new MyThread("Tock", tt);
mt1.Thrd.Join();
mt2.Thrd.Join();
Console.WriteLine("Часы остановлены");
}
}
Ниже приведен результат выполнения этой программы.
тик так
тик так
тик так
тик так
тик так
Часы остановлены
Рассмотрим эту программу более подробно. В методе Main()
создается объект tt
типа TickTock
, который используется для запуска двух потоков на выполнение. Если в методе Run()
из класса MyThread
обнаруживается имя потока Tick
, соответствующее ходу часов "тик", то вызывается метод Tick()
. А если это имя потока Tock
, соответствующее ходу часов "так", то вызывается метод Tock()
. Каждый из этих методов вызывается пять раз подряд с передачей логического значения true
в качестве аргумента. Часы идут до тех пор, пока этим методам передается логическое значение true
, и останавливаются, как только передается логическое значение false
.
Самая важная часть рассматриваемой здесь программы находится в методах Tick()
и Tock()
. Начнем с метода Tick()
, код которого для удобства приводится ниже.
public void Tick(bool running) {
lock(lockOn) {
if(!running) { // остановить часы
Monitor.Pulse(lockOn); // уведомить любые ожидающие потоки
return;
}
Console.Write("тик ");
Monitor.Pulse(lockOn); // разрешить выполнение метода Tock()
Monitor.Wait(lockOn); // ожидать завершения метода Tock()
}
}
Прежде всего обратите внимание на код метода Tick()
в блоке lock
. Напомним, что методы Wait()
и Pulse()
могут использоваться только в синхронизированных блоках кода. В начале метода Tick()
проверяется значение текущего параметра, которое служит явным признаком остановки часов. Если это логическое значение false
, то часы остановлены. В этом случае вызывается метод Pulse(), разрешающий выполнение любого потока, ожидающего своей очереди. Мы еще вернемся к этому моменту в дальнейшем. Если же часы идут при выполнении метода Tick()
, то на экран выводится слово "тик" с пробелом, затем вызывается метод Pulse()
, а после него — метод Wait()
. При вызове метода Pulse()
разрешается выполнение потока для того же самого объекта, а при вызове метода Wait()
выполнение метода Tick()
приостанавливается до тех пор, пока метод Pulse()
не будет вызван из другого потока. Таким образом, когда вызывается метод Tick()
, отображается одно слово "тик" с пробелом, разрешается выполнение другого потока, а затем выполнение данного метода приостанавливается.
Метод Тоск()
является точной копией метода Tick()
, за исключением того, что он выводит на экран слово "так". Таким образом, при входе в метод Тоск()
на экран выводится слово "так", вызывается метод Pulse()
, а затем выполнение метода Тоск()
приостанавливается. Методы Tick()
и Тоск()
можно рассматривать как поочередно сменяющие друг друга, т.е. они взаимно синхронизированы.
Когда часы остановлены, метод Pulse()
вызывается для того, чтобы обеспечить успешный вызов метода Wait()
. Напомним, что метод Wait()
вызывается в обоих методах, Tick()
и Тоск()
, после вывода соответствующего слова на экран. Но дело в том, что когда часы остановлены, один из этих методов все еще находится в состоянии ожидания. Поэтому завершающий вызов метода Pulse()
требуется, чтобы выполнить ожидающий метод до конца. В качестве эксперимента попробуйте удалить этот вызов метода Pulse()
и понаблюдайте за тем, что при этом произойдет. Вы сразу же обнаружите, что программа "зависает", и для выхода из нее придется нажать комбинацию клавиш . Дело в том, что когда метод Wait()
вызывается в последнем вызове метода Тоск()
, соответствующий ему метод Pulse()
не вызывается, а значит, выполнение метода Тоск()
оказывается незавершенным, и он ожидает своей очереди до бесконечности.
Интервал:
Закладка: