Составители:
Рубрика:
4.2. Использование потоков для организации ввода/вывода
Если вы не хотите, чтобы работа программного потока приостановилась
для выполнения процедур ввода/вывода, создайте второй программный поток
и поручите выполнение ввода/вывода ему. Тогда первый программный поток
сможет продолжить работу в то время, как второй поток будет выполнять мед-
лительные процедуры, связанные с вводом/выводом. Для реализации терми-
нальной программы, например, вы можете использовать два потока: один чи-
тает команды, вводимые с клавиатуры, а второй следит за поступлением
команд через последовательный порт. Оба потока записывают любые приня-
тые ими данные в циклический буфер. Третий поток проверяет содержимое
каждого из буферов и выполняет действия в соответствии с поступающими
командами. При этом скорость поступления данных через последовательный
порт не повлияет на скорость обработки команд, вводимых с клавиатуры.
При реализации подобного простого подхода обычно возникает проблема:
третий поток должен постоянно следить за изменением содержимого цикличе-
ских буферов, чтобы вовремя обнаружить появление в любом из них нового
символа. Таким образом, для его работы требуется дополнительное процессор-
ное время. Более сложная реализация может предусматривать использование со-
бытий (рассмотрены ранее при изучении многопоточности). Когда один из по-
токов ввода принимает символ, он переводит специально предназначенное для
этого событие в сигнальное состояние. При этом третий поток может использо-
вать для слежения за состоянием события функцию WaitForMultipleObjects(), т. е.
он не будет расходовать слишком много процессорного времени. Для слежения
за состоянием консоли можно использовать непосредственно дескриптор консо-
ли. Этот дескриптор переходит в сигнальное состояние в момент, когда в потоке
ввода консоли появляются данные, ожидающие чтения. Если вместо события
программа следит за состоянием дескриптора консоли, можно ограничиться
только двумя потоками.
Если терминальная программа обладает собственным циклом обработки
системных сообщений (к консольным приложениям это обычно не относится),
вы можете использовать другой подход. Потоки, осуществляющие ввод/вывод,
могут передавать основному окну программы сообщения, определенные поль-
зователем. Основная программа будет реагировать на эти сообщения так же,
как она реагирует на любые системные сообщения.
Все перечисленные стратегии очень просты в реализации, однако они не-
достаточно эффективны. Создание потоков – относительно ресурсоемкая опе-
рация. Кроме того, максимальное количество потоков, одновременно рабо-
тающих в системе, ограничено. Конечно, это не будет проблемой для простой
консольной программы, однако если ваше приложение должно поддерживать
интенсивный асинхронный ввод/вывод, применение для этой цели большого
количества потоков может оказаться неприемлемым.
64
4.2. Использование потоков для организации ввода/вывода
Если вы не хотите, чтобы работа программного потока приостановилась
для выполнения процедур ввода/вывода, создайте второй программный поток
и поручите выполнение ввода/вывода ему. Тогда первый программный поток
сможет продолжить работу в то время, как второй поток будет выполнять мед-
лительные процедуры, связанные с вводом/выводом. Для реализации терми-
нальной программы, например, вы можете использовать два потока: один чи-
тает команды, вводимые с клавиатуры, а второй следит за поступлением
команд через последовательный порт. Оба потока записывают любые приня-
тые ими данные в циклический буфер. Третий поток проверяет содержимое
каждого из буферов и выполняет действия в соответствии с поступающими
командами. При этом скорость поступления данных через последовательный
порт не повлияет на скорость обработки команд, вводимых с клавиатуры.
При реализации подобного простого подхода обычно возникает проблема:
третий поток должен постоянно следить за изменением содержимого цикличе-
ских буферов, чтобы вовремя обнаружить появление в любом из них нового
символа. Таким образом, для его работы требуется дополнительное процессор-
ное время. Более сложная реализация может предусматривать использование со-
бытий (рассмотрены ранее при изучении многопоточности). Когда один из по-
токов ввода принимает символ, он переводит специально предназначенное для
этого событие в сигнальное состояние. При этом третий поток может использо-
вать для слежения за состоянием события функцию WaitForMultipleObjects(), т. е.
он не будет расходовать слишком много процессорного времени. Для слежения
за состоянием консоли можно использовать непосредственно дескриптор консо-
ли. Этот дескриптор переходит в сигнальное состояние в момент, когда в потоке
ввода консоли появляются данные, ожидающие чтения. Если вместо события
программа следит за состоянием дескриптора консоли, можно ограничиться
только двумя потоками.
Если терминальная программа обладает собственным циклом обработки
системных сообщений (к консольным приложениям это обычно не относится),
вы можете использовать другой подход. Потоки, осуществляющие ввод/вывод,
могут передавать основному окну программы сообщения, определенные поль-
зователем. Основная программа будет реагировать на эти сообщения так же,
как она реагирует на любые системные сообщения.
Все перечисленные стратегии очень просты в реализации, однако они не-
достаточно эффективны. Создание потоков – относительно ресурсоемкая опе-
рация. Кроме того, максимальное количество потоков, одновременно рабо-
тающих в системе, ограничено. Конечно, это не будет проблемой для простой
консольной программы, однако если ваше приложение должно поддерживать
интенсивный асинхронный ввод/вывод, применение для этой цели большого
количества потоков может оказаться неприемлемым.
64
Страницы
- « первая
- ‹ предыдущая
- …
- 62
- 63
- 64
- 65
- 66
- …
- следующая ›
- последняя »
