4 просмотров

Синхронизация потоков и графического интерфейса в приложении Delphi

Пример кода для приложения Delphi с графическим интерфейсом и несколькими потоками

  • Делиться
  • флипборд
  • Эл. адрес
  • MSCS, информатика, Осиекский университет

Зарко Гайич имеет опыт работы с SQL и практические знания систем баз данных, таких как MS SQL Server, Firebird, Interbase и Oracle. Он также владеет XML, DHTML и JavaScript.

Многопоточность в Delphi позволяет создавать приложения, включающие несколько одновременных путей выполнения.

Обычное приложение Delphi является однопоточным, что означает, что все объекты VCL получают доступ к своим свойствам и выполняют свои методы в этом единственном потоке. Чтобы ускорить обработку данных в приложении, включите один или несколько вторичных потоков.

Потоки процессора

А нить это канал связи от приложения к процессору. Однопотоковым программам требуется обмен данными в обоих направлениях (к процессору и от процессора) во время его выполнения; многопоточные приложения могут открывать несколько разных каналов, тем самым ускоряя выполнение.

Потоки и графический интерфейс

Когда в приложении запущено несколько потоков, возникает вопрос, как можно обновить свой графический интерфейс пользователя в результате выполнения потока. Ответ кроется в классе TThread Синхронизировать метод.

Чтобы обновить пользовательский интерфейс приложения или основной поток из дополнительного потока, необходимо вызвать метод Synchronize. Этот метод представляет собой потокобезопасный метод, позволяющий избежать многопоточных конфликтов, которые могут возникнуть при доступе к свойствам объекта или методам, которые не являются потокобезопасными, или при использовании ресурсов не в основном потоке выполнения.

Ниже приведен демонстрационный пример, в котором используется несколько кнопок с индикаторами выполнения, каждый из которых отображает текущее «состояние» выполнения потока.

блок MainU;
интерфейс
использует
Windows, сообщения, SysUtils, варианты, классы, графика, элементы управления, формы,
Диалоги, ComCtrls, StdCtrls, ExtCtrls;
тип
//класс перехватчика
TButton = класс (StdCtrls.TButton)
собственный поток: TThread;
Прогрессбар: TProgressBar;
конец;
TMyThread = класс (TThread)
частный
FCounter: целое число;
FCountTo: целое число;
FProgressBar: TProgressBar;
FOownerButton: TButton;
процедура ДоПрогресс;
процедура SetCountTo(const Value: Integer) ;
процедура SetProgressBar(const Value: TProgressBar) ;
процедура SetOwnerButton(const Value: TButton) ;
защищенный
процедура Выполнить; переопределить;
публичный
конструктор Create(CreateSuspended: Boolean) ;
свойство CountTo: Integer чтение FCountTo запись SetCountTo;
свойство ProgressBar: TProgressBar чтение FProgressBar запись SetProgressBar;
свойство OwnerButton: TButton чтение FownerButton запись SetOwnerButton;
конец;
TMainForm = класс (TForm)
Кнопка1: TButton;
ProgressBar1: TProgressBar;
Кнопка2: TButton;
ProgressBar2: TProgressBar;
Кнопка 3: TButton;
ProgressBar3: TProgressBar;
Кнопка4: TButton;
ProgressBar4: TProgressBar;
Кнопка5: TButton;
ProgressBar5: TProgressBar;
процедура Button1Click(Отправитель: TObject) ;
конец;
вар
Основная форма: TMainForm;
реализация

< TMyThread >
конструктор TMyThread.Create(CreateSuspended: Boolean) ;
начинать
унаследовано;
FСчетчик := 0;
FCountTo := MAXINT;
конец;
процедура TMyThread.DoProgress;
вар
PctDone: расширенный;
начинать
PctDone := (FCounter / FCountTo) ;
FProgressBar.Position := Round(FProgressBar.Step * PctDone) ;
FownerButton.Caption := FormatFloat('0.00%', PctDone * 100) ;
конец;
процедура TMyThread.Execute;
константа
Интервал = 1000000;
начинать
FreeOnTerminate := Истина;
FProgressBar.Max := FCountTo div Interval;
FProgressBar.Step := FProgressBar.Max;
в то время как FCounter < FCountTo сделать
начинать
если FCounter mod Interval = 0, то Synchronize(DoProgress);
Inc(FCounter) ;
конец;
FownerButton.Caption := 'Старт';
FownerButton.OwnedThread := ноль;
FProgressBar.Position := FProgressBar.Max;
конец;
процедура TMyThread.SetCountTo(const Value: Integer) ;
начинать
FCountTo := Значение;
конец;
процедура TMyThread.SetOwnerButton(const Value: TButton) ;
начинать
FownerButton := Значение;
конец;
процедура TMyThread.SetProgressBar(const Value: TProgressBar) ;
начинать
FProgressBar := Значение;
конец;
процедура TMainForm.Button1Click(Отправитель: TObject) ;
вар
Кнопка: TButton;
поток: TMyThread;
aProgressBar: TProgressBar;
начинать
aButton := TButton(Отправитель) ;
если не назначено (aButton.OwnedThread), то
начинать
aThread := TMyThread.Create(True) ;
aButton.OwnedThread := aThread;
aProgressBar := TProgressBar(FindComponent(StringReplace(aButton.Name, 'Кнопка', 'ProgressBar', []))) ;
aThread.ProgressBar := aProgressBar;
aThread.OwnerButton := aButton;
Поток.Резюме;
aButton.Caption := 'Пауза';
конец
еще
начинать
если aButton.OwnedThread.Suspended, то
aButton.OwnedThread.Resume
еще
aButton.OwnedThread.Suspend;
aButton.Caption := 'Выполнить';
конец;
конец;
конец.

голоса
Рейтинг статьи
Статья в тему:  Химчистка: как очистить одежду без воды?
Ссылка на основную публикацию
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x