Асинхронный ввод/вывод сиспользованием нескольких потоков

Перекрывающийся и расширенный ввод/вывод позволяют достигнуть асинхронного выполнения операций ввода/вывода в границах единственного потока, хотя для поддержки этой функциональности ОС делает собственные потоки. В том либо ином виде способы этого типа нередко употребляются в почти всех ранешних ОС для поддержки ограниченных форм выполнения асинхронных операций в однопоточных системах.

Но Асинхронный ввод/вывод сиспользованием нескольких потоков Windows обеспечивает многопоточную поддержку, потому становится вероятным достижение такого же эффекта за счет выполнения синхронных операций ввода/вывода в нескольких, выполняемых независимо потоках. Ранее эти способности уже были продемонстрированы на примере многопоточных серверов и программки grepMT (глава 7). Не считая того, потоки обеспечивают концептуально поочередный и, предположительно, еще более Асинхронный ввод/вывод сиспользованием нескольких потоков обычный метод выполнения асинхронных операций ввода/вывода. В качестве кандидатуры способам, применяемым в программках 14.1 и 14.2, можно было бы предоставить каждому сгустку свой дескриптор файла, тогда и любой из потоков мог бы обрабатывать в синхронном режиме каждую четвертую запись.

Таковой метод использования потоков продемонстрирован в программке atouMT, которая в книжке не приводится Асинхронный ввод/вывод сиспользованием нескольких потоков, но включена в материал, размещенный на Web-сайте. Программка atouMT не только лишь способна производиться под управлением хоть какой версии Windows, да и более ординарна по сопоставлению с хоть каким из 2-ух вариантов программ асинхронного ввода/вывода, так как учет использования ресурсов в данном случае наименее Асинхронный ввод/вывод сиспользованием нескольких потоков сложен. Каждый поток просто поддерживает собственные буферы в своем стеке и делает в цикле последовательность синхронных операций чтения, преобразования и записи. При всем этом производительность программки остается на довольно высочайшем уровне.

Примечание

В программке atouMT.с, которая находится на Web-сайте, содержатся комменты по поводу нескольких вероятных "ловушек", которые могут поджидать вас Асинхронный ввод/вывод сиспользованием нескольких потоков при организации доступа сразу нескольких потоков к одному и тому же файлу. А именно, все отдельные дескрипторы файлов должны создаваться при помощи функции CreateHandle, а не функции DuplicateHandle.

Лично я предпочитаю использовать многопоточную обработку файлов, а не асинхронные операции ввода/вывода. Потоки легче программировать, и почти всегда Асинхронный ввод/вывод сиспользованием нескольких потоков они обеспечивают более высшую производительность.

Есть два исключения из этого общепринятого правила. 1-ое из их, как было показано ранее в этой главе, касается ситуаций, в каких может быть только одна невыполненная операция, и в целях синхронизации можно использовать дескриптор файла. 2-ое, более принципиальное исключение встречается в случае портов окончания Асинхронный ввод/вывод сиспользованием нескольких потоков асинхронного ввода/вывода, о чем будет говориться в конце истинной главы.

Таймеры ожидания

Windows NT поддерживает таймеры ожидания (waitable timers), являющихся одним из типов объектов ядра, осуществляющих ожидание.

Вы всегда сможете сделать свой сигнал синхронизации, создав синхронизирующий поток, который устанавливает событие в итоге пробуждения после вызова функции Sleep. В программке serverNP (программка 11.3) сервер Асинхронный ввод/вывод сиспользованием нескольких потоков также употребляет синхронизирующий поток для повторяющейся широковещательной рассылки имени собственного канала. Потому таймеры ожидания обеспечивают хотя и несколько лишний, но удачный метод организации выполнения задач на повторяющейся базе либо в согласовании с определенным расписанием. А именно, таймер ожидания можно настроить таким макаром, чтоб сигнал был сгенерирован в строго Асинхронный ввод/вывод сиспользованием нескольких потоков определенное время.

Таймер ожидания может быть или синхронизирующим (synchronization timer), или сбрасываемым вручную уведомляющим (manual-reset notification timer) таймером. Синхронизирующий таймер связывается с функцией косвенного вызова, аналогичной процедуре окончания расширенного ввода/вывода, тогда как для синхронизации по сбрасываемому вручную уведомляющему таймеру употребляется функция ожидания.

Для начала будет нужно сделать Асинхронный ввод/вывод сиспользованием нескольких потоков дескриптор таймера, используя для этого функцию CreateWaitableTimer.

HANDLE CreateWaitableTimer(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, LPCTSTR lpTimerName);

2-ой параметр, bManualReset, определяет, таймер какого типа должен быть сотворен — синхронизирующий либо уведомляющий. В программке 14.3 употребляется синхронизирующий таймер, но, изменив комменты и настройку параметра, вы просто превратите его в уведомляющий таймер Асинхронный ввод/вывод сиспользованием нескольких потоков. Заметьте, что существует также функция OpenWaitableTimer, которая может использовать необязательное имя, предоставляемое третьим аргументом.

Сначало таймер создается в неактивном состоянии, но при помощи функции SetWaitableTimer его можно активизировать и указать исходную временную задержку, также продолжительность промежутка времени меж временами вырабатываемыми сигналами.

BOOL SetWaitableTimer(HANDLE hTimer, const LARGE_INTEGER *pDueTime Асинхронный ввод/вывод сиспользованием нескольких потоков, LONG IPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, BOOL fResume);

hTimer — действительный дескриптор таймера, сделанного с внедрением функции CreateWaitableTimer.

2-ой параметр, на который показывает указатель pDueTime, может принимать или положительные значения, надлежащие абсолютному времени, или отрицательные, надлежащие относительному времени, при этом фактические значения выражаются в единицах времени продолжительностью 100 наносекунд, а их Асинхронный ввод/вывод сиспользованием нескольких потоков формат описывается структурой FILETIME. Переменные типа FILETIME были введены в главе 3 и уже использовались нами в главе 6 в программке timep (программка 6.2).

Величина интервала меж сигналами, указываемая в 3-ем параметре, выражается в миллисекундах. Если это значение установлено равным 0, то таймер переводится в сигнальное состояние только один раз. При положительных значениях этого параметра таймер Асинхронный ввод/вывод сиспользованием нескольких потоков является повторяющимся и срабатывает временами до того времени, пока его действие не будет прекращено вызовом функции CancelWaitableTimer. Отрицательные значения обозначенного интервала не допускаются.

4-ый параметр, pfnCompletionRoutine, применяется в случае синхронизирующего таймера и показывает адресок процедуры окончания, которая вызывается при переходе таймера в сигнальное состояние и при условии, что Асинхронный ввод/вывод сиспользованием нескольких потоков поток перебегает в состояние дежурного ожидания. При вызове этой процедуры в качестве 1-го из аргументов употребляется указатель, определяемый пятым параметром, plArgToComplretionRoutine.

Установив синхронизирующий таймер, вы сможете перевести поток в состояние дежурного ожидания методом вызова функции SleepEx, чтоб обеспечить возможность вызова процедуры окончания. В случае сбрасываемого вручную уведомляющего таймера Асинхронный ввод/вывод сиспользованием нескольких потоков следует организовать ожидание перехода дескриптора таймера в сигнальное состояние. Дескриптор будет оставаться в сигнальном состоянии до последующего вызова функции SetWaitableTimer. Полная версия программки 14.3, находящаяся на Web-сайте, предоставляет вам возможность проводить собственные опыты, используя таймер избранного типа в купе с процедурой окончания либо ожиданием перехода дескриптора таймера в сигнальное Асинхронный ввод/вывод сиспользованием нескольких потоков состояние, что в конечном итоге дает четыре разные композиции.

Последний параметр, fResume, связан с режимами сбережения энергии. Для получения более подробной инфы по этому вопросу обратитесь к справочной документации.

Функция CancelWaitableTimer употребляется для отмены деяния вызванной перед этим функции SetWaitableTimer, но при всем этом не изменяет сигнальное состояние таймера. Чтоб Асинхронный ввод/вывод сиспользованием нескольких потоков это сделать, нужно в очередной раз вызвать функцию SetWaitableTimer.


astma-u-detej-kniga-dlya-detskogo-vracha.html
astragal-sherstistocvetkovij.html
astrahanki-ne-hotyat-rozhat-v-voskresene-zamestitel-predsedatelya-fonda-socialnogo-strahovaniya-rf-provel-soveshanie-v-eao.html