Задание 23. Асинхронное чтение из файла.




Тип задания: разработка.

Уровень сложности: повышенный.

При асинхронном чтении данных из файла, после выдачи команды на чтение, поток не блокируется до завершения операции, а продолжает свою работу. В ОС Windows асинхронный ввод-вывод называется перекрывающимся (overlapped) вводом-выводом. Асинхронный ввод-вывод в ОС Windows выполняют «обычные» ф-ции ReadFile и WriteFile, но файл при этом должен быть открыт в режиме FILE_FLAG_OVERLAPPED.

О завершении операции ввода-вывода можно узнать либо по факту перехода дескриптора файла в сигнальное состояние (этот способ не годится, если с файлом одновременно работает несколько потоков ввода-вывода), либо используя специальное событие, устанавливаемое ОС по завершению операции в сигнальное состояние. Дескриптор этого события должен находиться в структуре типа OVERLAPPED, адрес которой передается ф-циям асинхронного ввода-вывода.

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

Рекомендуемые источники:

· Столлингс В. Операционные системы, 4-е изд.: - М.: Изд. дом "Вильямс", 2002.

· Электронный справочник «Win32 Programmer’s Reference» из состава «MS SDK Help Files».

Проектное задание:

· Ознакомиться с механизмом асинхронного ввода-вывода ОС Windows.

· Изучить назначение и использование функций API для работы с событиями (events).

· Выполнить обзор соответствующих функций API.

· Разработать и реализовать программу согласно условию задачи.

· Разработать набор тестов для демонстрации работоспособности и правильности программы.

· Подготовить отчет по курсовому проекту.

Задача:

Реализовать программы для асинхронного чтения данных из файла с использованием дескриптора и множественного асинхронного чтения с использованием событий.

 

Спроектировать, закодировать и отладить программы.

 

Язык реализации – произвольный, ОС – Windows.


ПРИЛОЖЕНИЕ Б

(Блок- схема алгоритма работы программы)

 


ПРИЛОЖЕНИЕ В

(Листинг программной реализации асинхронного чтения с файла)

#include <iostream>

#include <windows.h>

#include <process.h>

using namespace std;

const int N=1019000;//Количество читаемых байт

HANDLE hFile;

HANDLE hEvent1,hEvent2;

int threadsWork=0;

char* rus(char* message)

{

char* tmp=new char[strlen(message)+1];

CharToOem(message,tmp);

return tmp;

}

void Monitor1(void *)

{

DWORD dwWaitResult=1;

while(dwWaitResult!=WAIT_OBJECT_0)//Если чтение не завершилось

{

dwWaitResult = WaitForSingleObject(hEvent1,1); //Ожидаем событие окончания чтения

cout<<rus("\nВремя ожидания 1 потока вышло");

}

threadsWork--;

cout<<rus("\n1 поток завершил чтение");

_endthread();//завершение потока

}

 

void Monitor2(void *)

{

DWORD dwWaitResult=1;

while(dwWaitResult!=WAIT_OBJECT_0)//Если чтение не завершилось

{

dwWaitResult = WaitForSingleObject(hEvent2,1);//Ожидаем событие окончания чтения

cout<<rus("\nВремя ожидания 2 потока вышло");

}

threadsWork--;

cout<<rus("\n2 поток завершил чтение");

_endthread();//завершение потока

}

void thread1(void*)

{

char inBuffer[N+1]="\0";

DWORD nBytesToRead=N,nBytesRead,dwError;

hEvent1=CreateEvent(NULL,true,false,"event1");//создаем событие окончания чтения

if(hEvent1==NULL)

{

char error[30];

sprintf(error,"Такое событие уже существует (ошибка %d)",GetLastError());

cout<<rus(error)<<endl;

system("pause");

exit(-1);

}

OVERLAPPED gOverLapped;

// подготавливаем поля структуры асинхронной операции

gOverLapped.Offset = 0;

gOverLapped.OffsetHigh = 0;

gOverLapped.hEvent = hEvent1;

bool bResult;

//do{

// пытаемся провести асинхронную операцию чтения

bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead,&gOverLapped);

// если возникает проблема или асинхронная операция

// все еще ожидает обработки...

if (!bResult&&GetLastError()==ERROR_HANDLE_EOF)

{

// мы достигли конца файла

// в течение вызова к ReadFile

cout<<rus("\nМы достигли конца файла");

//break;

} // конец процедуры if

//cout<<" 1="<<inBuffer<<endl;

//gOverLapped.Offset+=nBytesRead;}while(bResult);

cout<<rus("\n1 поток закончил свою работу!");

CloseHandle(hEvent1);//Закрытие дескриптора события

_endthread();//завершение потока

}

void thread2(void*)

{

char inBuffer[N+1]="\0";

DWORD nBytesToRead=N,nBytesRead,dwError;

hEvent2=CreateEvent(NULL,true,false,"event2");//создаем событие окончания чтения

if(hEvent2==NULL)

{

char error[30];

sprintf(error,"Такое событие уже существует (ошибка %d)",GetLastError());

cout<<rus(error)<<endl;

system("pause");

exit(-1);

}

OVERLAPPED gOverLapped;

// подготавливаем поля структуры асинхронной операции

gOverLapped.Offset = 0;

gOverLapped.OffsetHigh = 0;

gOverLapped.hEvent = hEvent2;

bool bResult;

//do{

// пытаемся провести асинхронную операцию чтения

bResult = ReadFile(hFile, &inBuffer, nBytesToRead, &nBytesRead,&gOverLapped);

// если достигли конца файла

if (!bResult&&GetLastError()==ERROR_HANDLE_EOF)

{

// мы достигли конца файла

// в течение вызова к ReadFile

cout<<rus("\nМы достигли конца файла");

//break;

} // конец процедуры if

//cout<<" 2="<<inBuffer<<endl;

//gOverLapped.Offset+=nBytesRead;}while(bResult);

cout<<rus("\n2 поток закончил свою работу!");

CloseHandle(hEvent2);//Закрытие дескриптора события

_endthread();//завершение потока

}

void main()

{

if (_beginthread(Monitor1,1024,NULL)==-1)//Запуск монитора события первого потока

cout <<rus("\nОшибка запуска потока 1 монитора\n")<< endl;

if (_beginthread(Monitor2,1024,NULL)==-1)//Запуск монитора события второго потока

cout << rus("\nОшибка запуска потока 2 монитора\n")<< endl;

char fileName[]="D:\\file1.txt\0";

hFile=CreateFile(fileName, // Открываемый файл

GENERIC_READ, // Открываем для чтения

FILE_SHARE_READ, // Для совместного чтения

NULL, // Защита по умолчанию

OPEN_EXISTING, // Только существующий файл

FILE_ATTRIBUTE_NORMAL, // Обычный файл

NULL); // Атрибутов шаблона нет

if (hFile == INVALID_HANDLE_VALUE) //Если возникла ошибка

{

char error[30];

sprintf(error,"Не удалось открыть файл (ошибка %d)",GetLastError());

cout<<rus(error)<<endl;

system("pause");

exit(-1);

}

if (_beginthread(thread2,1024,NULL)==-1)//Запуск второго потока чтения

cout <<rus("\nОшибка запуска 2 потока\n")<< endl;

else threadsWork++;

if (_beginthread(thread1,1024,NULL)==-1)//Запуск первого потока чтения

cout <<rus("\nОшибка запуска 1 потока\n")<< endl;

else threadsWork++;

while(threadsWork);//Ожидание завершения потоков чтения

CloseHandle(hFile);//Закрытие файла

cout<<endl;

system("pause");

}



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2017-12-12 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: