Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
3_СПОС_курсач_2009.doc
Скачиваний:
2
Добавлен:
09.11.2018
Размер:
208.9 Кб
Скачать

Задание 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");

}