- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C# 4.0: полное руководство - Герберт Шилдт
Шрифт:
Интервал:
Закладка:
В методе MyTask() #2, подсчет равен 5
.....В методе MyTask() #1, подсчет равен 6
В методе MyTask() #2, подсчет равен 6
....В методе MyTask() #1, подсчет равен 7
В методе MyTask() #2, подсчет равен 7
.....В методе MyTask() #1, подсчет равен 8
В методе MyTask() #2, подсчет равен 8
.....В методе MyTask() #2, подсчет равен 9
MyTask №2 завершен
В методе MyTask() #1, подсчет равен 9
MyTask №1 завершен
............Основной поток завершен.
Применение методов ожидания
В приведенных выше примерах основной поток исполнения, а по существу, метод Main(), завершался потому, что такой результат гарантировали вызовы метода Thread.Sleep(). Но подобный подход нельзя считать удовлетворительным.
Организовать ожидание завершения задач можно и более совершенным способом, применяя методы ожидания, специально предоставляемые в классе Task. Самым простым из них считается метод Wait(), приостанавливающий исполнение вызывающего потока до тех пор, пока не завершится вызываемая задача. Ниже приведена простейшая форма объявления этого метода.
public void Wait()
При выполнении этого метода могут быть сгенерированы два исключения. Первым из них является исключение ObjectDisposedException. Оно генерируется в том случае, если задача освобождена посредством вызова метода Dispose(). А второе исключение, AggregateException, генерируется в том случае, если задача сама генерирует исключение или же отменяется. Как правило, отслеживается и обрабатывается именно это исключение. В связи с тем что задача может сгенерировать не одно исключение, если, например, у нее имеются порожденные задачи, все подобные исключения собираются в единое исключение типа AggregateException. Для того чтобы выяснить, что же произошло на самом деле, достаточно проанализировать внутренние исключения, связанные с этим совокупным исключением. А до тех пор в приведенных далее примерах любые исключения, генерируемые задачами, будут обрабатываться во время выполнения.
Ниже приведен вариант предыдущей программы, измененный с целью продемонстрировать применение метода Wait() на практике. Этот метод используется внутри метода Main(), чтобы приостановить его выполнение до тех пор, пока не завершатся обе задачи tsk и tsk2.
// Применить метод Wait().
using System;
using System.Threading;
using System.Threading.Tasks;
class DemoTask {
// Метод, исполняемый как задача,
static void MyTask() {
Console.WriteLine("MyTask() №" + Task.CurrentId + " запущен");
for(int count = 0; count < 10; count++) {
Thread.Sleep(500);
Console.WriteLine("В методе MyTask() #" + Task.CurrentId +
", подсчет равен " + count );
}
Console.WriteLine("MyTask №" + Task.CurrentId + " завершен");
}
static void Main() {
Console.WriteLine("Основной поток запущен.");
// Сконструировать объекты двух задач.
Task tsk = new Task(MyTask);
Task tsk2 = new Task(MyTask);
// Запустить задачи на исполнение,
tsk.Start();
tsk2.Start() ;
Console.WriteLine("Идентификатор задачи tsk: " + tsk.Id);
Console.WriteLine("Идентификатор задачи tsk2: " + tsk2.Id);
// Приостановить выполнение метода Main() до тех пор,
// пока не завершатся обе задачи tsk и tsk2
tsk.Wait();
tsk2.Wait() ;
Console.WriteLine("Основной поток завершен.");
}
}
При выполнении этой программы получается следующий результат.
Основной поток запущен.
Идентификатор задачи tsk: 1
Идентификатор задачи tsk2: 2
MyTask() №1 запущен
MyTask() №2 запущен
В методе MyTask() #1, подсчет равен 0
В методе MyTask() #2, подсчет равен 0
В методе MyTask() #2, подсчет равен 1
В методе MyTask() #1, подсчет равен 1
В методе MyTask() #2, подсчет равен 2
В методе MyTask() #1, подсчет равен 2
В методе MyTask() #2, подсчет равен 3
В методе MyTask() #1, подсчет равен 3
В методе MyTask() #2, подсчет равен 4
В методе MyTask() #1, подсчет равен 4
В методе MyTask() #2, подсчет равен 5
В методе MyTask() #1, подсчет равен 5
В методе MyTask() #2, подсчет равен 6
В методе MyTask() #1, подсчет равен 6
В методе MyTask() #2, подсчет равен 7
В методе MyTask() #1, подсчет равен 7
В методе MyTask() #2, подсчет равен 8
В методе MyTask() #1, подсчет равен 8
В методе MyTask() #2, подсчет равен 9
MyTask №2 завершен
В методе MyTask() #1, подсчет равен 9
MyTask №1 завершен
Основной поток завершен.
Как следует из приведенного выше результата, выполнение метода Main() приостанавливается до тех пор, пока не завершатся обе задачи tsk и tsk2. Следует, однако, иметь в виду, что в рассматриваемой здесь программе последовательность завершения задач tsk и tsk2 не имеет особого значения для вызовов метода Wait(). Так, если первой завершается задача tsk2, то в вызове метода tsk.Wait() будет по-прежнему ожидаться завершение задачи tsk. В таком случае вызов метода tsk2.Wait() приведет к выполнению и немедленному возврату из него, поскольку задача tsk2 уже завершена.
В данном случае оказывается достаточно двух вызовов метода Wait(), но того же результата можно добиться и более простым способом, воспользовавшись методом WaitAll(). Этот метод организует ожидание завершения группы задач. Возврата из него не произойдет до тех пор, пока не завершатся все задачи. Ниже приведена простейшая форма объявления этого метода.
public static void WaitAll(params Task[] tasks)
Задачи, завершения которых требуется ожидать, передаются с помощью параметра в виде массива tasks. А поскольку этот параметр относится к типу params, то данному методу можно отдельно передать массив объектов типа Task или список задач. При этом могут быть сгенерированы различные исключения, включая и AggregateException.
Для того чтобы посмотреть, как метод WaitAll() действует на практике, замените в приведенной выше программе следующую последовательность вызовов.
tsk.Wait();
tsk2.Wait();
на
Task.WaitAll(tsk, tsk2);
Программа будет работать точно так же, но логика ее выполнения станет более понятной.
Организуя ожидание завершения нескольких задач, следует быть особенно внимательным, чтобы избежать взаимоблокировок. Так, если две задачи ожидают завершения друг друга, то вызов метода WaitAll() вообще не приведет к возврату из него. Разумеется, условия для взаимоблокировок возникают в результате ошибок программирования, которых следует избегать. Следовательно, если вызов метода WaitAll() не приводит к возврату из него, то следует внимательно проанализировать, могут ли две задачи или больше взаимно блокироваться. (Вызов метода Wait(), который не приводит к возврату из него, также может стать причиной взаимоблокировок.)
Иногда требуется организовать ожидание до тех пор, пока не завершится любая из группы задач. Для этой цели служит метод WaitAny(). Ниже приведена простейшая форма его объявления.
public static int WaitAny(params Task[] tasks)
Задачи, завершения которых требуется ожидать, передаются с помощью параметра в виде массива tasks объектов типа Task или отдельного списка аргументов типа Task. Этот метод возвращает индекс задачи, которая завершается первой. При этом могут быть сгенерированы различные исключения.