Составители:
5.3.2. Механизмы асинхронного ввода-вывода
Асинхронный ввод/вывод можно реализовать несколькими разными способами.
Проще всего создать новый программный поток и осуществлять весь ввод/ вывод сред-
ствами этого потока. Вместо этого можно использовать перекрывающийся ввод/вывод
или порты завершения ввода/вывода. Еще одной технологией, с помощью которой
можно реализовать асинхронный ввод-вывод является технология проецирования фай-
лов, рассмотренная ранее.
Использование потоков. Если вы не хотите, чтобы работа программного потока
приостановилась для выполнения процедур ввода/вывода, создайте второй программный
поток и поручите выполнение ввода/вывода ему. Тогда первый программный поток
сможет продолжить работу в то время, как второй поток будет выполнять медлительные
процедуры, связанные с вводом/выводом. Например, для реализации терминальной про-
граммы вы можете использовать два потока: один читает команды, вводимые с клавиа-
туры, а второй следит за поступлением команд через последовательный порт. Оба пото-
ка записывают любые принятые ими данные в циклический буфер. Третий поток
проверяет содержимое каждого из буферов и выполняет действия в соответствии с по-
ступающими командами. При этом скорость поступления данных через последователь-
ный порт не повлияет на скорость обработки команд, вводимых с клавиатуры.
При реализации подобного простого подхода обычно возникает проблема: третий
поток должен постоянно следить за изменением содержимого циклических буферов,
чтобы вовремя обнаружить появление в любом из них нового символа. Таким образом,
для его работы требуется дополнительное процессорное время. Более сложная реализа-
ция может предусматривать использование событий (рассмотрены ранее при изучении
многопоточности). Когда один из потоков ввода принимает символ, он переводит специ-
ально предназначенное для этого событие в сигнальное состояние. При этом третий по-
ток может использовать для слежения за состоянием события функцию WaitForMultip-
leObjects(). To есть он не будет расходовать слишком много процессорного времени. Для
слежения за состоянием консоли можно использовать непосредственно дескриптор кон-
соли. Этот дескриптор переходит в сигнальное состояние в момент, когда в потоке ввода
консоли появляются данные, ожидающие чтения. Если вместо события программа сле-
дит за состоянием дескриптора консоли, можно ограничиться только двумя потоками.
Если терминальная программа обладает собственным циклом обработки систем-
ных сообщений (к консольным приложениям это обычно не относится), вы можете ис-
пользовать другой подход. Потоки, осуществляющие ввод/вывод, могут передавать ос-
новному окну программы сообщения, определенные пользователем. Основная
программа будет реагировать на эти сообщения так же, как она реагирует на любые сис-
темные сообщения.
Все перечисленные стратегии очень просты в реализации, однако они недостаточ-
но эффективны. Создание потоков - относительно ресурсоемкая операция. Кроме того,
максимальное количество потоков, одновременно работающих в системе, ограничено.
Конечно, это не будет проблемой для простой консольной программы, однако, если ва-
ше приложение должно поддерживать интенсивный асинхронный ввод/вывод, примене-
ние для этой цели большого количества потоков может оказаться неприемлемым.
Перекрывающийся ввод/вывод. Значительно более эффективным способом реали-
зации асинхронного ввода/вывода в Windows является перекрывающийся ввод/вывод. В
Windows эта разновидность ввода/вывода поддерживается в отношении фактически всех
типов файлов. В частности, вы можете применить перекрывающийся ввод/вывод в от-
ношении дисковых файлов, коммуникационных портов, именованных каналов (named
pipes) и сетевых сокетов. В общем и целом, если в отношении чего-либо можно приме-
137
5.3.2. Механизмы асинхронного ввода-вывода
Асинхронный ввод/вывод можно реализовать несколькими разными способами.
Проще всего создать новый программный поток и осуществлять весь ввод/ вывод сред-
ствами этого потока. Вместо этого можно использовать перекрывающийся ввод/вывод
или порты завершения ввода/вывода. Еще одной технологией, с помощью которой
можно реализовать асинхронный ввод-вывод является технология проецирования фай-
лов, рассмотренная ранее.
Использование потоков. Если вы не хотите, чтобы работа программного потока
приостановилась для выполнения процедур ввода/вывода, создайте второй программный
поток и поручите выполнение ввода/вывода ему. Тогда первый программный поток
сможет продолжить работу в то время, как второй поток будет выполнять медлительные
процедуры, связанные с вводом/выводом. Например, для реализации терминальной про-
граммы вы можете использовать два потока: один читает команды, вводимые с клавиа-
туры, а второй следит за поступлением команд через последовательный порт. Оба пото-
ка записывают любые принятые ими данные в циклический буфер. Третий поток
проверяет содержимое каждого из буферов и выполняет действия в соответствии с по-
ступающими командами. При этом скорость поступления данных через последователь-
ный порт не повлияет на скорость обработки команд, вводимых с клавиатуры.
При реализации подобного простого подхода обычно возникает проблема: третий
поток должен постоянно следить за изменением содержимого циклических буферов,
чтобы вовремя обнаружить появление в любом из них нового символа. Таким образом,
для его работы требуется дополнительное процессорное время. Более сложная реализа-
ция может предусматривать использование событий (рассмотрены ранее при изучении
многопоточности). Когда один из потоков ввода принимает символ, он переводит специ-
ально предназначенное для этого событие в сигнальное состояние. При этом третий по-
ток может использовать для слежения за состоянием события функцию WaitForMultip-
leObjects(). To есть он не будет расходовать слишком много процессорного времени. Для
слежения за состоянием консоли можно использовать непосредственно дескриптор кон-
соли. Этот дескриптор переходит в сигнальное состояние в момент, когда в потоке ввода
консоли появляются данные, ожидающие чтения. Если вместо события программа сле-
дит за состоянием дескриптора консоли, можно ограничиться только двумя потоками.
Если терминальная программа обладает собственным циклом обработки систем-
ных сообщений (к консольным приложениям это обычно не относится), вы можете ис-
пользовать другой подход. Потоки, осуществляющие ввод/вывод, могут передавать ос-
новному окну программы сообщения, определенные пользователем. Основная
программа будет реагировать на эти сообщения так же, как она реагирует на любые сис-
темные сообщения.
Все перечисленные стратегии очень просты в реализации, однако они недостаточ-
но эффективны. Создание потоков - относительно ресурсоемкая операция. Кроме того,
максимальное количество потоков, одновременно работающих в системе, ограничено.
Конечно, это не будет проблемой для простой консольной программы, однако, если ва-
ше приложение должно поддерживать интенсивный асинхронный ввод/вывод, примене-
ние для этой цели большого количества потоков может оказаться неприемлемым.
Перекрывающийся ввод/вывод. Значительно более эффективным способом реали-
зации асинхронного ввода/вывода в Windows является перекрывающийся ввод/вывод. В
Windows эта разновидность ввода/вывода поддерживается в отношении фактически всех
типов файлов. В частности, вы можете применить перекрывающийся ввод/вывод в от-
ношении дисковых файлов, коммуникационных портов, именованных каналов (named
pipes) и сетевых сокетов. В общем и целом, если в отношении чего-либо можно приме-
137
Страницы
- « первая
- ‹ предыдущая
- …
- 133
- 134
- 135
- 136
- 137
- …
- следующая ›
- последняя »
