Составители:
Рубрика:
отреагировать на завершение операции (особенно на многопро-
цессорных машинах), однако ценой увеличения загрузки процес-
сора, что может снизить общую производительность системы.
Функция WriteFile возвращает значение TRUE, если операция за-
писи завершена синхронно, а в случае ошибки или начатой
асинхронной операции она возвращает FALSE, поэтому требует-
ся анализ кода возникшей «ошибки», которая может и не яв-
ляться ошибкой.
2. Выполнение асинхронных операций с ожиданием на объектах
ядра:
ov.Offset = 12345;
ov.hEvent = CreateEvent((LPSECURITY_ATTRIBUTES)NULL, TRUE, FALSE, 0);
if (
WriteFile( fh, buffer, sizeof(buffer), &dwWritten, &ov ) ||
GetLastError() == ERROR_IO_PENDING
) {
/* пока операция ввода-вывода выполняется, выполняем некоторые
операции...
дожидаемся завершения операции ввода-вывода */
GetOverlappedResult( fh, &ov, &dwWritten, TRUE );
} else {
/* возникла ошибка */
}
Функция GetOverlappedResult в данном случае проверяет состо-
яние операции и, если она еще не завершена, вызывает функ-
цию WaitForSingleObject для ожидания завершения операции
ввода-вывода. Объект «событие» можно не создавать – в этом
случае функция будет ожидать освобождения объекта «файл»;
однако в случае нескольких, накладывающихся друг на друга,
асинхронных операций будет непонятно, какая именно опера-
ция завершилась, и использование специфичных для каждой
операции событий снимает эту проблему.
Ожидание на объектах ядра является наиболее экономным, но
реакция приложения на завершение ввода-вывода связана с ра-
ботой планировщика, поэтому для достижения малых задержек
иногда надо дополнительно повышать приоритеты потоков, пе-
реходящих в режим ожидания завершения ввода-вывода.
3. Выполнение асинхронных операций с использованием функ-
ций завершения операций ввода-вывода. Эта функция будет ав-
томатически вызвана после завершения ввода-вывода и может
Основы многозадачности
205
HasOverlappedIoCompleted и некоторые другие. Существует несколько вари-
антов использования асинхронного ввода-вывода; рассмотрим их на
небольшом примере.
Для начала надо описать необходимые переменные и открыть файл с
разрешением асинхронных операций (FILE_FLAG_OVERLAPPED):
OVERLAPPED ov;
DWORD dwWritten;
BYTE buffer[ 5000000 ];
HANDLE fh = CreateFile(
“file.dat”, FILE_READ_DATA|FILE_WRITE_DATA,
FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL
);
if ( fh == INVALID_HANDLE_VALUE ) {
/* возникла ошибка */
}
ZeroMemory( &ov, sizeof(OVERLAPPED) );
FillMemory( buffer, sizeof(buffer), 123 );
1. Выполнение асинхронных операций с опросом состояния; этот
способ может обеспечить самую быструю реакцию на заверше-
ние операции ввода-вывода, но ценой более высокой загрузки
процессора:
ov.Offset = 12345;
if (
WriteFile( fh, buffer, sizeof(buffer), &dwWritten, &ov ) ||
GetLastError() == ERROR_IO_PENDING
) {
/* пока операция ввода-вывода выполняется,
выполняем некоторые операции.
дожидаемся завершения операции ввода-вывода */
while (!GetOverlappedResult(fh, &ov, &dwWritten, FALSE)){}
} else {
/* возникла ошибка */
}
Функция GetOverlappedResult в данном случае проверяет состоя-
ние операции ввода-вывода и возвращает признак ее завершения.
Опрос состояния операции в цикле позволяет наиболее быстро
204
CIL и системное программирование в Microsoft .NET
204 CIL и системное программирование в Microsoft .NET Основы многозадачности 205 HasOverlappedIoCompleted и некоторые другие. Существует несколько вари- отреагировать на завершение операции (особенно на многопро- антов использования асинхронного ввода-вывода; рассмотрим их на цессорных машинах), однако ценой увеличения загрузки процес- небольшом примере. сора, что может снизить общую производительность системы. Для начала надо описать необходимые переменные и открыть файл с Функция WriteFile возвращает значение TRUE, если операция за- разрешением асинхронных операций (FILE_FLAG_OVERLAPPED): писи завершена синхронно, а в случае ошибки или начатой асинхронной операции она возвращает FALSE, поэтому требует- OVERLAPPED ov; ся анализ кода возникшей «ошибки», которая может и не яв- DWORD dwWritten; ляться ошибкой. BYTE buffer[ 5000000 ]; 2. Выполнение асинхронных операций с ожиданием на объектах ядра: HANDLE fh = CreateFile( “file.dat”, FILE_READ_DATA|FILE_WRITE_DATA, ov.Offset = 12345; FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL, OPEN_ALWAYS, ov.hEvent = CreateEvent((LPSECURITY_ATTRIBUTES)NULL, TRUE, FALSE, 0); FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL ); if ( if ( fh == INVALID_HANDLE_VALUE ) { WriteFile( fh, buffer, sizeof(buffer), &dwWritten, &ov ) || /* возникла ошибка */ GetLastError() == ERROR_IO_PENDING } ) { /* пока операция ввода-вывода выполняется, выполняем некоторые ZeroMemory( &ov, sizeof(OVERLAPPED) ); операции... FillMemory( buffer, sizeof(buffer), 123 ); дожидаемся завершения операции ввода-вывода */ GetOverlappedResult( fh, &ov, &dwWritten, TRUE ); 1. Выполнение асинхронных операций с опросом состояния; этот } else { способ может обеспечить самую быструю реакцию на заверше- /* возникла ошибка */ ние операции ввода-вывода, но ценой более высокой загрузки } процессора: Функция GetOverlappedResult в данном случае проверяет состо- яние операции и, если она еще не завершена, вызывает функ- ov.Offset = 12345; цию WaitForSingleObject для ожидания завершения операции if ( ввода-вывода. Объект «событие» можно не создавать – в этом WriteFile( fh, buffer, sizeof(buffer), &dwWritten, &ov ) || случае функция будет ожидать освобождения объекта «файл»; GetLastError() == ERROR_IO_PENDING однако в случае нескольких, накладывающихся друг на друга, ) { асинхронных операций будет непонятно, какая именно опера- /* пока операция ввода-вывода выполняется, ция завершилась, и использование специфичных для каждой выполняем некоторые операции. операции событий снимает эту проблему. дожидаемся завершения операции ввода-вывода */ Ожидание на объектах ядра является наиболее экономным, но while (!GetOverlappedResult(fh, &ov, &dwWritten, FALSE)){} реакция приложения на завершение ввода-вывода связана с ра- } else { ботой планировщика, поэтому для достижения малых задержек /* возникла ошибка */ иногда надо дополнительно повышать приоритеты потоков, пе- } реходящих в режим ожидания завершения ввода-вывода. Функция GetOverlappedResult в данном случае проверяет состоя- 3. Выполнение асинхронных операций с использованием функ- ние операции ввода-вывода и возвращает признак ее завершения. ций завершения операций ввода-вывода. Эта функция будет ав- Опрос состояния операции в цикле позволяет наиболее быстро томатически вызвана после завершения ввода-вывода и может
Страницы
- « первая
- ‹ предыдущая
- …
- 107
- 108
- 109
- 110
- 111
- …
- следующая ›
- последняя »