1
0
mirror of https://github.com/loginov-dmitry/multithread.git synced 2024-11-28 09:33:03 +02:00

pas-файлы сохранены в кодировке UTF-8

This commit is contained in:
loginov-dmitry 2020-07-02 09:26:15 +03:00
parent 271b6a0790
commit 98fdc4ed9f
13 changed files with 137 additions and 218 deletions

View File

@ -80,15 +80,6 @@ object Form1: TForm1
ScrollBars = ssVertical
TabOrder = 2
end
object Button1: TButton
Left = 304
Top = 168
Width = 201
Height = 25
Caption = #1047#1072#1087#1091#1089#1090#1080#1090#1100' Sleep-'#1087#1086#1090#1086#1082
TabOrder = 3
OnClick = Button1Click
end
object Timer1: TTimer
Interval = 500
OnTimer = Timer1Timer

View File

@ -1,4 +1,4 @@
unit CalcTimeQuantUnit;
unit CalcTimeQuantUnit;
interface
@ -9,29 +9,24 @@ uses
type
TCalcQuantThread = class(TThread)
private
// Добавляет длительность интервала активности (квант времени)
// Добавляет длительность интервала активности (квант времени)
procedure AddToWorkList(WorkTime: Double);
// Добавляет длительность интервала бездействия (в спящем состоянии)
// Добавляет длительность интервала бездействия (в спящем состоянии)
procedure AddToNotWorkList(NotWorkTime: Double);
protected
procedure Execute; override;
public
ThreadNum: Integer; // Номер потока
IsFinish: Boolean; // Флаг "работа потока завершена"
WorkAll: Double; // Общее время работы
NotWorkAll: Double; // Общее время бездействия
LoopCount: Integer; // Количество циклов
WorkList: array of Double; // Длительность выделенных квантов времени
NotWorkList: array of Double; // Длительность интервалов простоя
ThreadNum: Integer; // Номер потока
IsFinish: Boolean; // Флаг "работа потока завершена"
WorkAll: Double; // Общее время работы
NotWorkAll: Double; // Общее время бездействия
LoopCount: Integer; // Количество циклов
WorkList: array of Double; // Длительность выделенных квантов времени
NotWorkList: array of Double; // Длительность интервалов простоя
constructor Create(ThreadNum: Integer);
end;
TSleepThread = class(TThread)
protected
procedure Execute; override;
end;
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
@ -40,16 +35,13 @@ type
Label3: TLabel;
Memo1: TMemo;
Timer1: TTimer;
Button1: TButton;
procedure btnStartThreadsClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
FList: TList; // Список запущенных потоков
SleepThread: TSleepThread;
FList: TList; // Список запущенных потоков
public
{ Public declarations }
end;
@ -71,11 +63,6 @@ begin
btnStartThreads.Enabled := False;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
SleepThread := TSleepThread.Create(False);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FList := TList.Create;
@ -103,13 +90,13 @@ begin
T := TCalcQuantThread(FList[I]);
if T.IsFinish then
begin
s := Format('Интервалы активности потока #%d (Общее время=%f; Число квантов=%d; '+
'Число циклов=%d): ', [T.ThreadNum, T.WorkAll, Length(T.WorkList), T.LoopCount]);
s := Format('Интервалы активности потока #%d (Общее время=%f; Число квантов=%d; '+
'Число циклов=%d): ', [T.ThreadNum, T.WorkAll, Length(T.WorkList), T.LoopCount]);
for Q in T.WorkList do
s := s + FormatFloat('0.0000', Q) + ',';
Memo1.Lines.Add(s);
s := Format('Интервалы бездействия потока #%d (Общее время=%f; Число интервалов '+
'бездействия=%d): ', [T.ThreadNum, T.NotWorkAll, Length(T.NotWorkList)]);
s := Format('Интервалы бездействия потока #%d (Общее время=%f; Число интервалов '+
'бездействия=%d): ', [T.ThreadNum, T.NotWorkAll, Length(T.NotWorkList)]);
for Q in T.NotWorkList do
s := s + FormatFloat('0.0000', Q) + ',';
Memo1.Lines.Add(s + sLineBreak);
@ -161,26 +148,19 @@ begin
QueryPerformanceCounter(CurTicks);
Inc(LoopCount);
if CurTicks - PrevTicks > QuantDiff then
begin // Если разница оказалась больше 1 мс, значит ОС приостанавливала
// работу потока и теперь начался отсчёт нового кванта
AddToWorkList(CurQuantTime / Freq); // Сохраняем время работы потока
AddToNotWorkList((CurTicks - PrevTicks) / Freq); // Сохраняем время простоя потока
begin // Если разница оказалась больше 1 мс, значит ОС приостанавливала
// работу потока и теперь начался отсчёт нового кванта
AddToWorkList(CurQuantTime / Freq); // Сохраняем время работы потока
AddToNotWorkList((CurTicks - PrevTicks) / Freq); // Сохраняем время простоя потока
CurQuantStart := CurTicks;
CurQuantTime := 0;
end else
CurQuantTime := CurTicks - CurQuantStart;
PrevTicks := CurTicks;
until (CurTicks - StartTicks) > BreakDiff;
if CurQuantTime > 0 then // Обрабатываем длительность последнего кванта
if CurQuantTime > 0 then // Обрабатываем длительность последнего кванта
AddToWorkList(CurQuantTime / Freq);
IsFinish := True;
end;
{ TSleepThread }
procedure TSleepThread.Execute;
begin
while not Terminated do Sleep(1);
end;
end.

View File

@ -1,4 +1,4 @@
{
{
Copyright (c) 2020, Loginov Dmitry Sergeevich
All rights reserved.
@ -34,14 +34,13 @@ uses
type
TThreadAccessTerminated = class(TThread);
// Подсказка самому себе, где находится TObjectList
// Подсказка самому себе, где находится TObjectList
TObjectListHelp = class(Contnrs.TObjectList);
// Простой пример организации паузы в работе потока с контролем свойства Terminate
// Простой пример организации паузы в работе потока с контролем свойства Terminate
procedure ThreadWaitTimeout(AThread: TThread; ATimeout: Integer);
// Эмуляция полезной работы
// Эмуляция полезной работы
procedure EmulateUsefullWork(WorkTime: Integer);
procedure ThreadShowMessageFmt(Msg: string; Args: array of const);
@ -68,61 +67,61 @@ begin
Sleep(WorkTime);
end;
// Реализация, основанная на функции GetTickCount
// Реализация, основанная на функции GetTickCount
{procedure ThreadWaitTimeout(AThread: TThread; ATimeout: Integer);
var
StartTime, Diff, tc: Cardinal;
T: TThreadAccessTerminated;
begin
// Получаем доступ к protected-свойству Terminated
// Получаем доступ к protected-свойству Terminated
T := TThreadAccessTerminated(AThread);
// Если поток нужно завершить, то сразу выходим из цикла
// Если поток нужно завершить, то сразу выходим из цикла
if T.Terminated then Exit;
// Запоминаем текущее время (в миллисекундах от включения компьютера)
// Запоминаем текущее время (в миллисекундах от включения компьютера)
StartTime := GetTickCount;
while True do
begin
tc := GetTickCount;
// Прерываем ожидание, если функция GetTickCount начала новый круг
// иначе наша функция ожидания может зависнуть
// Прерываем ожидание, если функция GetTickCount начала новый круг
// иначе наша функция ожидания может зависнуть
if (tc < StartTime) then Exit;
// Прерываем ожидание, если превысили указанный таймаут
// Прерываем ожидание, если превысили указанный таймаут
Diff := tc - StartTime;
if (Diff >= ATimeout) or T.Terminated then
Exit;
// Замораживаем поток примерно на 20 мс
// Замораживаем поток примерно на 20 мс
Sleep(20);
end;
end; }
// Реализация, основанная на TPerformance
// Реализация, основанная на TPerformance
procedure ThreadWaitTimeout(AThread: TThread; ATimeout: Integer);
var
p: TTimeInterval;
T: TThreadAccessTerminated;
begin
// Получаем доступ к protected-свойству Terminated
// Получаем доступ к protected-свойству Terminated
T := TThreadAccessTerminated(AThread);
// Если поток нужно завершить, то сразу выходим из цикла
// Если поток нужно завершить, то сразу выходим из цикла
if T.Terminated then Exit;
p.Start; // Начинаем замер времени
p.Start; // Начинаем замер времени
while True do
begin
if T.Terminated or (p.ElapsedMilliseconds >= ATimeout) then
Exit;
// Замораживаем поток примерно на 20 мс
// Замораживаем поток примерно на 20 мс
Sleep(ThreadWaitTimeoutSleepTime);
end;
end;
initialization
// Критическая секция для защиты строк от
// одновременного доступа из разных потоков
// Критическая секция для защиты строк от
// одновременного доступа из разных потоков
StringProtectSection := TCriticalSection.Create;
finalization

View File

@ -1,4 +1,4 @@
unit Ex1Unit;
unit Ex1Unit;
interface
@ -35,7 +35,7 @@ var
I: Integer;
begin
Result := 0;
// Очень длинный цикл. Имитирует длительные вычисления.
// Очень длинный цикл. Имитирует длительные вычисления.
for I := 1 to MaxInt do
Result := Result + Random(1000);
end;
@ -47,7 +47,7 @@ end;
procedure TForm1.btnRunInParallelThreadClick(Sender: TObject);
begin
// Запускает параллельный поток
// Запускает параллельный поток
TMyThread.Create(False);
end;
@ -59,7 +59,7 @@ var
begin
FreeOnTerminate := True;
V := DoLongCalculations;
MyShowMessage('Результат: ' + IntToStr(V));
MyShowMessage('Результат: ' + IntToStr(V));
end;
procedure TForm1.btnRunInMainThreadClick(Sender: TObject);
@ -67,7 +67,7 @@ var
V: Int64;
begin
V := DoLongCalculations;
MyShowMessage('Результат: ' + IntToStr(V));
MyShowMessage('Результат: ' + IntToStr(V));
end;
end.

View File

@ -1,4 +1,4 @@
unit Ex2Unit;
unit Ex2Unit;
interface
@ -9,7 +9,7 @@ uses
type
TMyLongThread = class(TThread)
private
procedure DoUsefullTask; // Процедура для имитации полезной работы
procedure DoUsefullTask; // Процедура для имитации полезной работы
public
procedure Execute; override;
end;
@ -34,20 +34,20 @@ implementation
procedure TForm1.btnRunParallelThreadClick(Sender: TObject);
begin
// Запускает параллельный поток
// Запускает параллельный поток
if MyThread = nil then
MyThread := TMyLongThread.Create(False)
else
raise Exception.Create('Дополнительный поток уже запущен!');
raise Exception.Create('Дополнительный поток уже запущен!');
end;
{ TMyLongThread }
procedure TMyLongThread.DoUsefullTask;
begin
// Реальный поток может выполнять какую угодно полезную работу
// В учебных целях делаем паузу 5 секунд для имитации задержки, которая
// может возникнуть при выполнении полезной работы
// Реальный поток может выполнять какую угодно полезную работу
// В учебных целях делаем паузу 5 секунд для имитации задержки, которая
// может возникнуть при выполнении полезной работы
Sleep(5000);
end;
@ -60,14 +60,14 @@ begin
while not Terminated do
begin
DoUsefullTask;
WaitTimeout(10000); // Ожидаем таймаут 10 сек.
WaitTimeout(10000); // Ожидаем таймаут 10 сек.
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
// При закрытии программы необходимо завершить работу потока
// и уничтожить объект потока MyThread
// При закрытии программы необходимо завершить работу потока
// и уничтожить объект потока MyThread
if MyThread <> nil then
MyThread.Free;
end;

View File

@ -1,4 +1,4 @@
unit Ex3Unit;
unit Ex3Unit;
interface
@ -9,7 +9,7 @@ uses
type
TMyShortThread = class(TThread)
private
procedure DoUsefullTask; // Процедура для имитации полезной работы
procedure DoUsefullTask; // Процедура для имитации полезной работы
public
procedure Execute; override;
end;
@ -34,8 +34,8 @@ implementation
procedure TForm1.btnRunParallelThreadClick(Sender: TObject);
begin
// Запускает параллельный поток. Если объект потока уже создан,
// то уничтожает его.
// Запускает параллельный поток. Если объект потока уже создан,
// то уничтожает его.
if MyThread <> nil then
FreeAndNil(MyThread);
MyThread := TMyShortThread.Create(False);
@ -47,10 +47,10 @@ procedure TMyShortThread.DoUsefullTask;
var
AProgress: TProgressViewer;
begin
// Реальный поток может выполнять какую угодно полезную работу
// В учебных целях делаем паузу 5 секунд для имитации задержки, которая
// может возникнуть при выполнении полезной работы
AProgress := TProgressViewer.Create('Выполняется поток TMyShortThread');
// Реальный поток может выполнять какую угодно полезную работу
// В учебных целях делаем паузу 5 секунд для имитации задержки, которая
// может возникнуть при выполнении полезной работы
AProgress := TProgressViewer.Create('Выполняется поток TMyShortThread');
Sleep(5000);
AProgress.TerminateProgress;
end;
@ -62,8 +62,8 @@ end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
// При закрытии программы необходимо завершить работу потока
// и уничтожить объект потока MyThread
// При закрытии программы необходимо завершить работу потока
// и уничтожить объект потока MyThread
if MyThread <> nil then
MyThread.Free;
end;

View File

@ -1,4 +1,4 @@
unit Ex4Unit;
unit Ex4Unit;
interface
@ -10,9 +10,9 @@ type
TMyLongThread = class(TThread)
private
FTaskNum: Integer;
procedure DoUsefullTask1; // Первая задача
procedure DoUsefullTask2; // Вторая задача
procedure DoFinalizeTask; // Задача запускается при завершении работы потока
procedure DoUsefullTask1; // Первая задача
procedure DoUsefullTask2; // Вторая задача
procedure DoFinalizeTask; // Задача запускается при завершении работы потока
public
constructor Create(TaskNum: Integer);
procedure Execute; override;
@ -26,8 +26,8 @@ type
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
MyThread1: TMyLongThread; // Поток для первой задачи
MyThread2: TMyLongThread; // Поток для второй задачи
MyThread1: TMyLongThread; // Поток для первой задачи
MyThread2: TMyLongThread; // Поток для второй задачи
public
{ Public declarations }
end;
@ -41,11 +41,11 @@ implementation
procedure TForm1.btnRunParallelThreadsClick(Sender: TObject);
begin
// Запускает параллельный поток для задачи 1
// Запускает параллельный поток для задачи 1
if MyThread1 = nil then
MyThread1 := TMyLongThread.Create(1);
// Запускает параллельный поток для задачи 2
// Запускает параллельный поток для задачи 2
if MyThread2 = nil then
MyThread2 := TMyLongThread.Create(2);
end;
@ -54,25 +54,25 @@ end;
constructor TMyLongThread.Create(TaskNum: Integer);
begin
inherited Create(False); // Вызываем родительский конструктор
inherited Create(False); // Вызываем родительский конструктор
// Запоминаем параметр TaskNum. Он нужен в методе Execute
// Запоминаем параметр TaskNum. Он нужен в методе Execute
FTaskNum := TaskNum;
end;
procedure TMyLongThread.DoFinalizeTask;
begin
Sleep(5000); // Данная условная задача занимает 5 секунд
Sleep(5000); // Данная условная задача занимает 5 секунд
end;
procedure TMyLongThread.DoUsefullTask1;
begin
Sleep(1000); // Данная условная задача занимает 1 секунду
Sleep(1000); // Данная условная задача занимает 1 секунду
end;
procedure TMyLongThread.DoUsefullTask2;
begin
Sleep(2000); // Данная условная задача занимает 2 секунды
Sleep(2000); // Данная условная задача занимает 2 секунды
end;
procedure TMyLongThread.Execute;
@ -85,17 +85,17 @@ begin
begin
if Terminated then
begin
DoFinalizeTask; // Некоторые действия при завершении потока
Exit; // Завершаем работу потока
DoFinalizeTask; // Некоторые действия при завершении потока
Exit; // Завершаем работу потока
end else
begin
if FTaskNum = 1 then
DoUsefullTask1 // Запускаем задачу 1
DoUsefullTask1 // Запускаем задачу 1
else
DoUsefullTask2; // Запускаем задачу 2
DoUsefullTask2; // Запускаем задачу 2
if not Terminated then // Дополнительная проверка не повредит!
WaitTimeout(1000); // Ожидаем таймаут 1 сек
if not Terminated then // Дополнительная проверка не повредит!
WaitTimeout(1000); // Ожидаем таймаут 1 сек
end;
end;
end;
@ -104,14 +104,14 @@ procedure TForm1.FormDestroy(Sender: TObject);
var
AProgress: TProgressViewer;
begin
AProgress := TProgressViewer.Create('Выход из программы');
AProgress := TProgressViewer.Create('Выход из программы');
try
if cbTerminateMode.ItemIndex = 1 then
begin // Выбран режим "Одновременно (быстрее)"
begin // Выбран режим "Одновременно (быстрее)"
if Assigned(MyThread1) then
MyThread1.Terminate; // Выставляем флаг Terminated
MyThread1.Terminate; // Выставляем флаг Terminated
if Assigned(MyThread2) then
MyThread2.Terminate; // Выставляем флаг Terminated
MyThread2.Terminate; // Выставляем флаг Terminated
end;
MyThread1.Free;
MyThread2.Free;

View File

@ -1,4 +1,4 @@
unit Ex5Unit;
unit Ex5Unit;
interface
@ -42,7 +42,7 @@ type
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
FList: TObjectList; // Потоки для первой и второй задачи
FList: TObjectList; // Потоки для первой и второй задачи
public
{ Public declarations }
end;
@ -56,7 +56,7 @@ implementation
procedure TForm1.btnRunParallelThreadsClick(Sender: TObject);
begin
// Запускаем 4 параллельных потока
// Запускаем 4 параллельных потока
if FList.Count = 0 then
begin
FList.Add(TMyLongThread1.Create(1000));
@ -70,7 +70,7 @@ end;
constructor TMyLongThread1.Create(UsefullTaskTime: Integer);
begin
inherited Create(False); // Вызываем родительский конструктор
inherited Create(False); // Вызываем родительский конструктор
FUsefullTaskTime := UsefullTaskTime;
end;
@ -79,9 +79,9 @@ begin
while not Terminated do
begin
EmulateUsefullWork(FUsefullTaskTime);
ThreadWaitTimeout(Self, 60000); // Ожидаем таймаут 60 сек
ThreadWaitTimeout(Self, 60000); // Ожидаем таймаут 60 сек
end;
Sleep(5000); // Оставлено для демонстрации режима "Одновременно"
Sleep(5000); // Оставлено для демонстрации режима "Одновременно"
end;
procedure TForm1.FormCreate(Sender: TObject);
@ -94,16 +94,16 @@ var
AProgress: TProgressViewer;
I: Integer;
begin
AProgress := TProgressViewer.Create('Выход из программы');
AProgress := TProgressViewer.Create('Выход из программы');
try
if cbTerminateMode.ItemIndex = 1 then
begin // Выбран режим "Одновременно (быстрее)"
// Выставляем флаг Terminated для всех потоков. Можно использовать
// родительский класс TThread для операции приведения типов.
begin // Выбран режим "Одновременно (быстрее)"
// Выставляем флаг Terminated для всех потоков. Можно использовать
// родительский класс TThread для операции приведения типов.
for I := 0 to FList.Count - 1 do
TThread(FList[I]).Terminate;
end;
// При уничтожении списка TObjectList будут уничтожены все объекты потоков
// При уничтожении списка TObjectList будут уничтожены все объекты потоков
FList.Free;
finally
AProgress.TerminateProgress;
@ -117,9 +117,9 @@ begin
while not Terminated do
begin
EmulateUsefullWork(2000);
ThreadWaitTimeout(Self, 60000); // Ожидаем таймаут 60 сек
ThreadWaitTimeout(Self, 60000); // Ожидаем таймаут 60 сек
end;
Sleep(5000); // Оставлено для демонстрации режима "Одновременно"
Sleep(5000); // Оставлено для демонстрации режима "Одновременно"
end;
{ TMyLongThread3 }
@ -135,9 +135,9 @@ begin
while not Terminated do
begin
EmulateUsefullWork(FUsefullTaskTime);
ThreadWaitTimeout(Self, 60000); // Ожидаем таймаут 60 сек
ThreadWaitTimeout(Self, 60000); // Ожидаем таймаут 60 сек
end;
Sleep(5000); // Оставлено для демонстрации режима "Одновременно"
Sleep(5000); // Оставлено для демонстрации режима "Одновременно"
end;
{ TMyLongThread4 }
@ -147,9 +147,9 @@ begin
while not Terminated do
begin
EmulateUsefullWork(1000);
ThreadWaitTimeout(Self, 60000); // Ожидаем таймаут 60 сек
ThreadWaitTimeout(Self, 60000); // Ожидаем таймаут 60 сек
end;
Sleep(5000); // Оставлено для демонстрации режима "Одновременно"
Sleep(5000); // Оставлено для демонстрации режима "Одновременно"
end;
end.

View File

@ -1,4 +1,4 @@
unit Ex6Unit;
unit Ex6Unit;
interface
@ -36,7 +36,7 @@ implementation
procedure TForm1.btnRunInParallelThreadClick(Sender: TObject);
begin
// Запускаем параллельный поток
// Запускаем параллельный поток
TMyThread.Create;
end;
@ -44,13 +44,13 @@ procedure TForm1.FormDestroy(Sender: TObject);
var
pv: TProgressViewer;
begin
// Выставляем флаг StopThreadsFlag, чтобы все потоки завершились
// Выставляем флаг StopThreadsFlag, чтобы все потоки завершились
StopThreadsFlag := True;
// Задерживаем выход из программы, пока не будут завершены все потоки
// Задерживаем выход из программы, пока не будут завершены все потоки
if ThreadCount > 0 then
begin
pv := TProgressViewer.Create('Ожидаем завершение потоков');
pv := TProgressViewer.Create('Ожидаем завершение потоков');
while ThreadCount > 0 do
Sleep(10);
pv.TerminateProgress;
@ -62,15 +62,15 @@ end;
constructor TMyThread.Create;
begin
inherited Create(False);
// Увеличиваем глобальную переменную ThreadCount на 1 и запоминаем
// полученное значение
// Увеличиваем глобальную переменную ThreadCount на 1 и запоминаем
// полученное значение
FThreadNum := InterlockedIncrement(ThreadCount);
end;
destructor TMyThread.Destroy;
begin
inherited;
// Уменьшаем глобальную переменную ThreadCount на 1
// Уменьшаем глобальную переменную ThreadCount на 1
InterlockedDecrement(ThreadCount);
end;
@ -80,17 +80,17 @@ var
begin
FreeOnTerminate := True;
// Организуем паузу 10 секунд. При этом каждые 20 мс
// проверяем флаг StopThreadsFlag
// Организуем паузу 10 секунд. При этом каждые 20 мс
// проверяем флаг StopThreadsFlag
ti.Start;
while ti.ElapsedSeconds < 10 do
begin
// Заканчиваем ожидание, если выставлен флаг StopThreadsFlag
// Заканчиваем ожидание, если выставлен флаг StopThreadsFlag
if StopThreadsFlag then Break;
Sleep(20);
end;
ThreadShowMessageFmt('Работа потока #%d завершена!', [FThreadNum]);
ThreadShowMessageFmt('Работа потока #%d завершена!', [FThreadNum]);
end;
end.

View File

@ -47,7 +47,6 @@ object Form1: TForm1
Height = 17
Anchors = [akLeft, akTop, akRight]
TabOrder = 1
ExplicitWidth = 519
end
object edMaxValue: TEdit
Left = 232

View File

@ -1,4 +1,4 @@
unit Ex7Unit;
unit Ex7Unit;
interface
@ -41,17 +41,17 @@ implementation
procedure TForm1.btnRunInParallelThreadClick(Sender: TObject);
begin
// Уничтожаем запущенный поток
// Уничтожаем запущенный поток
if Assigned(FMyThread) then
FreeAndNil(FMyThread);
// Создаём поток в спящем состоянии
// Создаём поток в спящем состоянии
FMyThread := TMyThread.Create(True);
// Запоминаем длину ряда в поле MaxValue
// Запоминаем длину ряда в поле MaxValue
FMyThread.MaxValue := StrToIntDef(edMaxValue.Text, 0);
// Пробуждаем поток для выполнения вычислений
// Пробуждаем поток для выполнения вычислений
FMyThread.Resume;
end;
@ -67,10 +67,10 @@ var
Res: Int64;
CurrVal: Integer;
begin
// Выставляем параметры компонента ProgressBar1
// Выставляем параметры компонента ProgressBar1
Synchronize(SetProgressParams);
// Выполняем некоторые вычисления
// Выполняем некоторые вычисления
Res := 0;
CurrVal := 0;
while CurrVal < MaxValue do
@ -80,14 +80,14 @@ begin
Res := Res + CurrVal;
if CurrVal mod 10000 = 0 then
begin // Обновление прогресса выполняется только 1 раз из 10000
begin // Обновление прогресса выполняется только 1 раз из 10000
FCurrValue := CurrVal;
FResult := Res;
Synchronize(SetProgressCurrValue);
end;
end;
// Обновляем прогресс в конце вычислений
// Обновляем прогресс в конце вычислений
FCurrValue := CurrVal;
FResult := Res;
Synchronize(SetProgressCurrValue);

View File

@ -70,24 +70,6 @@ object Form1: TForm1
TabOrder = 2
Text = '10000000'
end
object Button1: TButton
Left = 280
Top = 88
Width = 75
Height = 25
Caption = #1058#1077#1089#1090' '#1079#1072#1084#1077#1088#1086#1074
TabOrder = 3
OnClick = Button1Click
end
object Button2: TButton
Left = 280
Top = 120
Width = 75
Height = 25
Caption = 'Button2'
TabOrder = 4
OnClick = Button2Click
end
object Timer1: TTimer
Interval = 100
OnTimer = Timer1Timer

View File

@ -1,4 +1,4 @@
unit Ex8Unit;
unit Ex8Unit;
interface
@ -13,7 +13,7 @@ type
FResult: Int64;
FCurrValue: Integer;
// Èíôîðìàöèÿ î òåêóùåì ñîñòîÿíèè ïîòîêà
// Информация о текущем состоянии потока
FThreadStateInfo: string;
function GetThreadStateInfo: string;
@ -24,8 +24,8 @@ type
property CalcResult: Int64 read FResult;
property CurrValue: Integer read FCurrValue;
// Ñâîéñòâî äëÿ äîñòóïà ê ñòðîêå FThreadStateInfo ñ ïîìîùüþ
// ïîòîêîçàùèùåííûõ ìåòîäîâ GetThreadStateInfo è SetThreadStateInfo
// Свойство для доступа к строке FThreadStateInfo с помощью
// потокозащищенных методов GetThreadStateInfo и SetThreadStateInfo
property ThreadStateInfo: string read GetThreadStateInfo write SetThreadStateInfo;
end;
@ -38,13 +38,9 @@ type
Timer1: TTimer;
Label2: TLabel;
labThreadStateInfo: TLabel;
Button1: TButton;
Button2: TButton;
procedure btnRunInParallelThreadClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
FMyThread: TMyThread;
@ -62,7 +58,7 @@ procedure TForm1.btnRunInParallelThreadClick(Sender: TObject);
var
MaxValue: Integer;
begin
// Óíè÷òîæàåì çàïóùåííûé ïîòîê
// Уничтожаем запущенный поток
if Assigned(FMyThread) then
FreeAndNil(FMyThread);
@ -75,34 +71,6 @@ begin
FMyThread := TMyThread.Create(MaxValue);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
p: TTimeIntervalEvents;
begin
p.StartEvent('Ýòàï 1');
Sleep(1);
p.StopEvent('Ýòàï 1');
p.StartEvent('Ýòàï 2');
Sleep(20);
p.StopEvent('Ýòàï 2');
ShowMessage(p.GetEventsAsString([eoWriteStartTime, eoWriteAllTime,
eoUseMicroSec, eoWriteFromStart, eoWriteBegTime, eoWriteEndTime, eoWriteDate]));
//ShowMessage(p.GetEventsAsString([eoUseMicroSec]));
end;
procedure TForm1.Button2Click(Sender: TObject);
var
p: TTimeInterval;
begin
//p.Start;
p := TTimeInterval.StartNew;
Sleep(100);
ShowMessageFmt('%s', [FormatDateTime('hh:nn:ss.zzz', p.ElapsedTime)]);
ShowMessageFmt('%s', [FormatDateTime('hh:nn:ss.zzz', p.ElapsedTime)]);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FreeAndNil(FMyThread);
@ -143,19 +111,19 @@ end;
function TMyThread.GetThreadStateInfo: string;
begin
// Çàùèùàåì ñòðîêó ñ ïîìîùüþ êðèòè÷åñêîé ñåêöèè. Åñëè å¸ óáðàòü,
// òî â ãëàâíîì ïîòîêå ïåðèîäè÷åñêè áóäåò âîçíèêàòü îøèáêà
// "Invalid pointer operation" ëèáî "Out of memory"
StringProtectSection.Enter; // Âõîäèì â ðåæèì çàùèòû
// Защищаем строку с помощью критической секции. Если её убрать,
// то в главном потоке периодически будет возникать ошибка
// "Invalid pointer operation" либо "Out of memory"
StringProtectSection.Enter; // Входим в режим защиты
Result := FThreadStateInfo;
StringProtectSection.Leave; // Âûõîäèì èç ðåæèìà çàùèòû
StringProtectSection.Leave; // Выходим из режима защиты
end;
procedure TMyThread.SetThreadStateInfo(const Value: string);
begin
StringProtectSection.Enter; // Âõîäèì â ðåæèì çàùèòû
StringProtectSection.Enter; // Входим в режим защиты
FThreadStateInfo := Value;
StringProtectSection.Leave; // Âûõîäèì èç ðåæèìà çàùèòû
StringProtectSection.Leave; // Выходим из режима защиты
end;
end.