Многопоточные приложения
Многозадачность
Многозадачность в современных операционных системах воспринимается как нечто само собой разумеющееся [До появления Apple OS X на компьютерах Macintosh не было современных многозадачных операционных систем.Знакомство с многопоточностью
Каждая программа работает в определенном контексте, описывающем распределение кода и данных в памяти. При сохранении контекста фактически сохраняется состояние программного потока, что позволяет в будущем восстановить его и продолжить выполнение программы.Домены приложений
Программные потоки .NET работают в так называемых доменах приложений, определяемых в документации как "изолированная среда, в которой выполняется приложение". Домен приложения можно рассматривать как облегченный вариант процессов Win32;Создание потоков
Начнем с элементарного примера. Допустим, вы хотите запустить в отдельном потоке процедуру, которая в бесконечном цикле уменьшает значение счетчика.Метод Join. Имена потоков, CurrentThread и ThreadState.
Иногда программный поток требуется приостановить до момента завершения другого потока. Допустим, вы хотите приостановить поток 1 до тех пор, пока поток 2 не завершит свои вычисления. Для этого из потока 1 вызывается метод Join для потока 2.Окно потоков. Приостановка потока.
Окно потоков (Threads window) Visual Studio .NET оказывает неоценимую помощь в отладке многопоточных программ. Оно активизируется командой подменю Debug › Windows в режиме прерывания.Завершение или прерывание программных потоков
Поток автоматически завершается при выходе из метода, указанного при создании делегата ThreadStart, но иногда требуется завершить метод (следовательно, и поток) при возникновении определенных факторов.Приостановка и уничтожение потоков. Фоновые потоки (демоны).
Пространство имен Threading содержит и другие методы, прерывающие нормальное функционирование потоков: | Suspend; | Abort. | Трудно сказать, зачем в .NET была включена поддержка этих методов – при вызове Suspend и Abort программа, скорее всего, начнет работать нестабильно.Более серьезный пример: извлечение данных из кода HTML
Мы рекомендуем использовать потоки лишь в том случае, когда функциональность программы четко делится на несколько операций. Хорошим примером является программа извлечения данных из кода HTML из главы 9. Наш класс выполняет две операции: выборку данных с сайта Amazon и их обработку.Главная опасность (общие данные)
До настоящего момента рассматривался единственный безопасный случай использования потоков – наши потоки не изменяли общих данных. Если разрешить изменение общих данных, потенциальные ошибки начинают плодиться в геометрической прогрессии и избавить от них программу становится гораздо труднее.Решение проблемы: синхронизация
В предыдущей программе возникает ситуация, когда результат работы программы зависит от порядка выполнения потоков. Чтобы избавиться от нее, необходимо убедиться в том, что команды типа: | If mHouse.HouseTemp < mHouse.MAX_TEMP -5 Then… | Полностью отрабатываются активным потоком до того, как он будет прерван.Команда SyncLock и класс Monitor
Использование команды SyncLock связано с некоторыми тонкостями, не проявившимися в приведенных выше простых примерах. Так, очень важную роль играет выбор объекта синхронизации. Попробуйте запустить предыдущую программу с командой SyncLock(Me) вместо SyncLock(mHouse).Взаимная блокировка
В процессе синхронизации блокировка устанавливается для объектов, а не потоков, поэтому при использовании разных объектов для блокировки разных фрагментов кода в программах иногда возникают весьма нетривиальные ошибки.Совместная работа с данными по мере их создания
В многопоточных приложениях часто встречается ситуация, когда потоки не только работают с общими данными, но и ожидают их появления (то есть поток 1 должен создать данные, прежде чем поток 2 сможет их использовать). Поскольку данные являются общими, доступ к ним необходимо синхронизировать.Многопоточность в графических программах
Наше обсуждение многопоточности в приложениях с графическим интерфейсом начнется с примера, поясняющего, для чего нужна многопоточность в графических приложениях. Создайте форму с двумя кнопками Start (btnStart) и Cancel (btnCancel), как показано на рис. 10.9.Следующий шаг: кнопка Show Count
Допустим, вы решили проявить творческую фантазию и придать форме вид, показанный на рис. 10.10. Обратите внимание: кнопка Show Count пока недоступна. | Рис. 10.10. Форма с заблокированной кнопкой | Предполагается, что отдельный поток выполняет подсчет и разблокирует недоступную кнопку.