Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОС СФМЭИ.doc
Скачиваний:
22
Добавлен:
17.09.2019
Размер:
1.37 Mб
Скачать

7.3 Примеры работы с объектами синхронизации

7.3.1 Пример 1

Пример 1 (см. рисунок 7.1) демонстрирует работу таких объектов синхронизации, как критические секции, объекты mutex и события. В приложении также рассматривается работа функции WaitForMultipleObjects в режиме ожидания освобождения всех объектов и в режиме ожидания освобождения какого-либо одного объекта.

На форму переносятся командные кнопки Button1-Button6 и компонент Memo1.

Для программирования приложения выполняются следующие действия:

  1. Определение глобальных переменных. Для этого в область VAR (после определения объекта Форма) добавляются следующие строки:

var

Form1: TForm1;

Sum:Integer; {Переменная, в которую записывается результат вычислений }

f:TextFile; {файловая переменная}

cs:TRTLCriticalSection; {критическая секция}

mt:THANDLE; {Дескриптор объекта mutex}

ev:THANDLE; {Дескриптор объекта «событие»}

  1. Пример работы критических секций. Работа критических секций рассматривается на следующем примере – создается два дополнительных потока. Первый поток занимает критическую секцию, увеличивает число на 1 и освобождает критическую секцию. Второй поток записывает очередное число, сформированное первым потоком в файл. Программирование кнопки «Критические секции».

  • Включите в текст приложения дополнительную функцию Thread1, которая выполняет вычисления (увеличивает число на 1):

procedure Thread1;

begin

While Sum<20 do

begin

EnterCriticalSection(cs);

Inc(Sum);

Sleep(30);

LeaveCriticalsection(cs);

end;

end;

  • Включите в текст приложения дополнительную функцию Thread2, которая записывает в файл результат вычислений функции Thread1:

procedure Thread2;

begin

While Sum <20 do

begin

EnterCriticalSection(cs);

Writeln(f,IntToStr(Sum));

Sleep(30);

LeaveCriticalsection(cs);

end;

end;

  • Для события OnClick кнопки «Критически секции» напишите следующий программный код:

procedure TForm1.Button1Click(Sender: TObject);

VAR hThread1,hThread2:THandle;

pFunc1,pFunc2:pointer;

ThreadID1,ThreadID2:CARDINAL;

begin

Sum:=0;

AssignFile(f,'C:\tempCS.txt');

Rewrite(f);

InitializeCriticalSection(cs);

pFunc1:=@Thread1;

pFunc2:=@Thread2;

hThread1:=CreateThread(nil,0,pFunc1,nil,0,ThreadID1);

hThread2:=CreateThread(nil,0,pFunc2,nil,0,ThreadID2);

While Sum<20 do

begin

EnterCriticalSection(cs);

Sleep(30);

LeaveCriticalSection(cs);

end;

ShowMessage ('Работа завершена');

CloseFile(f);

end;

  1. Пример работы с объектом mutex. Работа объекта mutex рассматривается на примере аналогичном рассмотренному в п.2 (работа с критическими секциями). Создается два дополнительных потока. Первый поток занимает объект mutex, увеличивает число на 1, выводит его значение в поле Memo1 и освобождает объект mutex. Второй поток записывает очередное число, сформированное первым потоком в файл. Программирование кнопки «Mutex»:

  • Включите в текст приложения дополнительную функцию Thread3, которая выполняет вычисления (увеличивает число на 1):

procedure Thread3;

begin

While Sum<20 do

begin

WaitForSingleObject(mt,INFINITE);

Inc(Sum);

Form1.Memo1.Lines.Add(IntToStr(sum));

Form1.Refresh;

ReleaseMutex(mt);

Sleep(20);

end;

end;

  • Включите в текст приложения дополнительную функцию Thread4, которая записывает в файл результат вычислений функции Thread3:

procedure Thread4;

begin

While Sum <20 do

begin

WaitForSingleObject(mt,INFINITE);

Writeln(f,IntToStr(Sum));

ReleaseMutex(mt);

Sleep(20);

end;

CloseFile(f);

end;

  • Для события OnClick кнопки «Mutex» напишите следующий программный код:

procedure TForm1.Button2Click(Sender: TObject);

VAR hThread3,hThread4:THandle;

pFunc3,pFunc4:pointer;

ThreadID3,ThreadID4:CARDINAL;

begin

Sum:=0;

Memo1.Clear;

// Form1.Refresh;

AssignFile(f,'C:\tempMT.txt');

Rewrite(f);

mt:=CreateMutex(nil,FALSE,PChar(''));

pFunc3:=@Thread3;

pFunc4:=@Thread4;

hThread3:=CreateThread(nil,0,pFunc3,nil,0,ThreadID3);

hThread4:=CreateThread(nil,0,pFunc4,nil,0,ThreadID4);

end;

  1. Пример работы с объектом «событие с автосбросом». Работа объекта «событие» рассматривается на примере аналогичном рассмотренному в пп. 2 и 3. Создается два дополнительных потока. Первый поток занимает объект «событие», увеличивает число на 1, выводит его значение в поле Memo1 и освобождает объект «событие». Второй поток записывает очередное число, сформированное первым потоком в файл. Программирование кнопки «События»:

  • Включите в текст приложения дополнительную функцию Thread5, которая выполняет вычисления (увеличивает число на 1):

procedure Thread5;

begin

While Sum<20 do

begin

WaitForSingleObject(ev,INFINITE);

Inc(Sum);

Form1.Memo1.Lines.Add(IntToStr(sum));

Form1.Refresh;

SetEvent(ev);

Sleep(20);

end;

end;

  • Включите в текст приложения дополнительную функцию Thread6, которая записывает в файл результат вычислений функции Thread5:

procedure Thread6;

begin

While Sum <20 do

begin

WaitForSingleObject(mt,INFINITE);

Writeln(f,IntToStr(Sum));

SetEvent(ev);

Sleep(20);

end;

CloseFile(f);

end;

  • Для события OnClick кнопки «События» напишите следующий программный код:

procedure TForm1.Button3Click(Sender: TObject);

VAR hThread5,hThread6:THandle;

pFunc5,pFunc6:pointer;

ThreadID5,ThreadID6:CARDINAL;

begin

Sum:=0;

Memo1.Clear;

Form1.Refresh;

AssignFile(f,'C:\tempEV.txt');

Rewrite(f);

ev:=CreateEvent(nil,FALSE,TRUE,PChar(''));

pFunc5:=@Thread5;

pFunc6:=@Thread6;

hThread5:=CreateThread(nil,0,pFunc5,nil,0,ThreadID5);

hThread6:=CreateThread(nil,0,pFunc6,nil,0,ThreadID6);

end;

  1. Пример работы функции WaitForMultipleObjects, которая ожидает завершения всех запущенных процессов. В примере запускается три процесса «Калькулятор» и приложение ожидает завершения всех трех процессов, после чего работа приложения может быть продолжена. Для события OnClick кнопки «Ожидание завершения всех процессов» напишите следующий программный код:

procedure TForm1.Button5Click(Sender: TObject);

VAR StartInfo:TStartUpInfo;

ProcInfo:TProcessInformation;

h:PWOHandleArray;

i:Integer;

err:Boolean;

begin

err:=False;

For i:=0 to 2 do

begin

//Очистка полей структуры StartInfo

FillChar(StartInfo,Sizeof(StartInfo),#0);

StartInfo.cb:=Sizeof(StartInfo);

If not CreateProcess(nil,'C:\WINNT\system32\calc.exe',nil,nil,False,

NORMAL_PRIORITY_CLASS,nil,nil,StartInfo,ProcInfo)

then

begin

ShowMessage('Ошибка '+IntToStr(GetLastError));

err:=True;

end

else

begin

h[i]:=ProcInfo.hProcess;

end;

end;

If not err

then WaitFormultipleObjects(3,h,True,INFINITE);

end;

  1. Пример работы функции WaitForMultipleObjects, которая ожидает завершения одного из запущенных процессов. В примере запускается три процесса «Калькулятор» и приложение ожидает завершения какого-либо одного процесса, после чего работа приложения может быть продолжена. Для события OnClick кнопки «Ожидание завершения одного из процессов» напишите следующий программный код:

procedure TForm1.Button6Click(Sender: TObject);

VAR StartInfo:TStartUpInfo;

ProcInfo:TProcessInformation;

h:PWOHandleArray;

i:Integer;

err:Boolean;

begin

err:=False;

For i:=0 to 2 do

begin

//Очистка полей структуры StartInfo

FillChar(StartInfo,Sizeof(StartInfo),#0);

StartInfo.cb:=Sizeof(StartInfo);

If not CreateProcess(nil,'C:\WINNT\system32\calc.exe',nil,nil,False,

NORMAL_PRIORITY_CLASS,nil,nil,StartInfo,ProcInfo)

then

begin

ShowMessage('Ошибка '+IntToStr(GetLastError));

err:=True;

end

else

begin

h[i]:=ProcInfo.hProcess;

end;

end;

If not err

then

WaitFormultipleObjects(3,h,False,INFINITE);

end;

  1. Завершение работы приложения. Для события OnClick кнопки «Выход» напишите следующий программный код:

procedure TForm1.Button4Click(Sender: TObject);

begin

Form1.Close;

end;