Автор работы: Пользователь скрыл имя, 24 Сентября 2011 в 12:57, курсовая работа
В курсовом проекте предлагается спроектировать и разработать программу, обеспечивающую мультизадачность. В программе необходимо предусмотреть два визуальных процесса: один для ввода с контролем и корректировки данных (выполнять все виды корректировки – добавление, удаление, замену) и вывода результатов указанного в задании запроса и второй - для выполнения запроса.
1.ЗАДАНИЕ 3
2.ВВЕДЕНИЕ 4
3. ПРОБЛЕМЫ ПРИ СИНХРОНИЗАЦИИ ПОТОКОВ 5
3.1 СИНХРОНИЗАЦИЯ 6
4. ФУНКЦИИ WINAPI32 7
4.1 КРИТИЧЕСКИЕ СЕКЦИИ 7
4.2 ПОТОКИ 8
4.3 КАНАЛЫ 9
5.ГРАФИЧЕСКОЕ ОТОБРАЖЕНИЕ ВЗАИМОДЕЙСТВИЯ ПОТОКОВ И ОБМЕНА ДАННЫМИ МЕЖДУ НИМИ 12
6. ОПИСАНИЕ ОСНОВНЫХ СОБЫТИЙ ПРИЛОЖЕНИЯ 13
7.РЕЗУЛЬТАТЫ ТЕСТОВЫХ ПРОГОНОВ 14
8.ЛИСТИНГ ПРОГРАММЫ 18
8.1 UNIT1 18
8.2 UNIT2 26
9. ВЫВОД 29
10. СПИСОК ЛИТЕРАТУРЫ 30
function TryEnterCriticalSection( var lpCriticalSection: TRTLCriticalSection): BOOL;
Она проверяет, захвачена секция ли в момент её вызова. Если да – функция возвращает FALSE, в противном случае – захватывает секцию и возвращает TRUE.
По завершении работы с критической секцией, она должна быть уничтожена вызовом функции:
procedure DeleteCriticalSection(var lpCriticalSection: TRTLCriticalSection);
Для создания потока существует функция
function CreateThread(nil,
dwStackSize : DWORD, //начальный размер стека в байтах
lpStartAddress : LPTHREAD_START_ROUTINE,
// указатель на функцию потока
Nil,0, //Поток создается и начинает свое выполнение.
lpThreadId : DWORD // указатель на код
//завершения потока
) : HANDLE
Параметры:
lpThreadAttributes
- указатель на структуру
dwStackSize
- указание этого параметра
lpStartAddress
- имя функции, выполняемой как
поток. Функция потока имеет
один 32-битный указатель типа LPVOID
в качестве аргумента и
lpThreadId-адрес переменной типа DWORD для размещения кода созданного потока
Если функция успешна, то возвращаемое значение есть идентификатор потока. Если функция неуспешна, то возвращаемое значение равно NULL.
Пример:
secondThread:=createthread(
2. Для приостановки выполнения текущего потока на определенный интервал времени существует функция
procedure
Sleep(dwMilliseconds : DWORD);
Каналы достаточно просты в использовании. Через канал можно передавать данные между двумя процессами или потоками. Один из процессов создает канал, другой открывает его. После этого оба процесса могут передавать данные через канал в одну или в обе стороны, используя для этого функции ReadFile и WriteFile.
Существует две разновидности каналов: именованные и анонимные. Именованному каналу при создании присваивается имя, которое доступно для других процессов. Анонимные каналы обычно используются для организации передачи данных между родительскими и дочерними процессами.
Имя канала имеет вид: \\.\\pipe\имя канала
Для создания
именованных каналов
HANDLE CreateNamedPipe( LPCTSTR lpName,
// адрес строки имени канала
dwOpenMode: PChar, // режим открытия канала
dwPipeMode: Cardinal, // режим работы канала
1,
nOutBufferSize: Cardinal,
// размер выходного буфера в байтах
nInBufferSize: Cardinal,
//
размер входного буфера в
nDefaultTimeOut: Cardinal,
// время ожидания в миллисекундах
nil ); // указатель на структуру атрибутов защиты
Если функция успешна, ее возвращаемое значение есть идентификатор серверного конца именованного канала.
Пример создания канала:
PipeID:=CreateNamedPipe('\\
После того, как серверный процесс создал именованный канал, он может перейти в режим ожидания, пока клиентский процесс не соединится с каналом. Для этого существует функция
ConnectNamedPipe(
HANDLE hNamedPipe, // идентификатор серверного конца именованного канала
nil ) : BOOL;
Если функция отработала успешно, то возвращаемое значение ненулевое.
Если функция выполнена неуспешно, то возвращаемое значение равно 0.
Пример:
ConnectNamedPipe(PipeID,
Для создания канала клиентский процесс должен воспользоваться функцией
HANDLE CreateFile(
LPCTSTR lpFileName: PChar,
//адрес строки с именем файла или именованного канала
dwDesiredAccess: Cardinal, // режим доступа
0,nil, OPEN_EXISTING,0,0 );
dwDesiredAccess
Этот параметр может принимать следующие значения:
GENERIC_READ | Разрешен доступ на чтение к файлу или каналу. |
GENERIC_WRITE | Разрешен доступ на запись к файлу или каналу. |
Пример:
ClPipeID:=CreateFile('\\.\
Для чтения данных из канала используется функция
ReadFile(hFile: HANDLE,
// идентификатор канала или файла
lpBuffer: Untyped, // адрес буфера для чтения
nNumberOfBytesToRead: Cardinal,
// число байт, которое необходимо прочитать
lpNumberOfBytesRead: Cardinal, // адрес поля, куда
/// запишется фактически прочитанное число байт
nil ): BOOL;
Если функция отработала успешно, то возвращаемое значение ненулевое. Если при этом число прочитанных байт равно 0, это означает, что указатель файла за пределом текущего конца файла.
Если функция неуспешна, то возвращаемое значение равно 0.
Пример:
ReadFile(PipeID,sam,sizeof(
Для записи данных в канал используется функция
WriteFile(hFile: HANDLE,
//идентификатор канала или файла
lpBuffer: Cardinal,
// адрес буфера для записи
nNumberOfBytesToWrite: Cardinal,
// число байт, которое необходимо записать
lpNumberOfBytesWritten: Cardinal,
// адрес поля, куда запишется фактически
//записанное число байт
nil) : BOOL;
Если функция успешна, то возвращаемое значение ненулевое.
Если
функция неуспешна, то возвращаемое
значение равно 0.
Пример:
WriteFile(PipeID,sam1,
Для закрытия канала существует функция
CloseHandle(hObject : HANDLE // идентификатор закрываемого объекта ): BOOL;
Если функция успешна, то возвращаемое значение ненулевое.
Если
функция неуспешна, то возвращаемое
значение равно 0.
При создании главной формы (первый поток) создается и захватывается объект синхронизации – критическая секция. Последовательно создается второй поток, который создает именованный канал, через этот канал будет осуществляться обмен данными между потоками, и ждет подключения первого потока. Первый поток подключается к именованному каналу. Так как объект синхронизации захвачен, второй поток не выполняет никаких действий, ждет освобождения критической секции.
После вода данных пользователем, первый поток записывает параметры запроса и необходимую для проведения расчетов информацию в именованный канал. Всё это время второй поток пребывает в состоянии ожидания.
После
записи необходимых данных в канал
первый поток освобождает критическую
секцию, давая возможность захватить объект
синхронизации второму потоку. Второй
поток захватывает критическую секцию.
Первый поток после этого переходит в
режим ожидания. Второй поток последовательно
считывает данные для осуществления запроса.
После чего обрабатывает их и записывает
в канал результаты работы. Затем он освобождает
критическую секцию, давая возможность
захватить объект синхронизации первому
потоку. Первый поток тут же его захватывает
. Второй поток переходит в режим ожидания.
Первый поток последовательно считывает
результаты из канала и выводит их
на экран, после чего программа переходит
в исходное состояние ожидания команд
пользователя.
Рисунок
1. Главное окно
Рисунок
2. Окно после запроса на “Кальций”
Рисунок
3. Окно для добавления
Рисунок
4. Окно для изменения
Рисунок
5. Окно после добавления
Рисунок
6. Окно после удаления “Анальгин”
Рисунок
7. Неправильно введено поле: цена
Рисунок
8. Неправильно введено поле: Номер аптеки
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, StdCtrls,
ExtCtrls;
type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
Izmenit: TButton;
Del: TButton;
Dobavit: TButton;
Panel1: TPanel;
Zapros: TButton;
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure StringGrid1Click(Sender: TObject);
procedure IzmenitClick(Sender: TObject);
procedure ZaprosClick(Sender: TObject);
procedure DobavitClick(Sender: TObject);
procedure
DelClick(Sender: TObject);
private
{ Private declarations }
public
{ Public
declarations }
end;
function Zaproc():integer;
procedure Vivod;
type
Apteka=record