멀티스레드 GUI 동기화
일반적인 Delphi 애플리케이션은 단일 스레드이므로
모든 VCL 객체가 속성에 액세스하고이 단일 스레드 내에서 메서드를 실행합니다.
애플리케이션에서 데이터 처리 속도를 높이려면 하나 이상의
보조 스레드를 포함하십시오.
프로세서 스레드
스레드 프로세서에 응용 프로그램의 통신 채널이다.
단일 스레드 프로그램은 실행시 양방향으로 (프로세서에서) 양방향으로 통신해야합니다.
다중 스레드 앱은 여러 채널을 열 수 있으므로 실행 속도가 빨라집니다.
스레드 및 GUI
애플리케이션에서 여러 스레드가 실행 중일 때 스레드 실행의 결과로
그래픽 사용자 인터페이스를 업데이트 할 수있는 방법에 대한 의문이 생깁니다.
대답은 TThread 클래스 Synchronize 메서드에 있습니다.
보조 스레드에서 애플리케이션의 사용자 인터페이스 또는 기본 스레드를 업데이트하려면
Synchronize 메서드를 호출해야합니다.
이 기술은 스레드로부터 안전하지 않은 개체 속성 또는
메서드에 액세스하거나 기본 실행 스레드에없는 리소스를 사용하여
발생할 수있는 다중 스레딩 충돌을 방지하는 스레드로부터 안전한 방법입니다.
아래는 진행률 표시 줄이있는 여러 버튼을 사용하는 예제 소스와 샘풀프로그램입니다.
각 진행률 표시 줄은 스레드 실행의 현재 "상태"를 표시합니다.
unit MainU;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, ExtCtrls;
type
//interceptor class
TButton = class(StdCtrls.TButton)
OwnedThread: TThread;
ProgressBar: TProgressBar;
end;
TMyThread = class(TThread)
private
FCounter: Integer;
FCountTo: Integer;
FProgressBar: TProgressBar;
FOwnerButton: TButton;
procedure DoProgress;
procedure SetCountTo(const Value: Integer) ;
procedure SetProgressBar(const Value: TProgressBar) ;
procedure SetOwnerButton(const Value: TButton) ;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean) ;
property CountTo: Integer read FCountTo write SetCountTo;
property ProgressBar: TProgressBar read FProgressBar write SetProgressBar;
property OwnerButton: TButton read FOwnerButton write SetOwnerButton;
end;
TMainForm = class(TForm)
Button1: TButton;
ProgressBar1: TProgressBar;
Button2: TButton;
ProgressBar2: TProgressBar;
Button3: TButton;
ProgressBar3: TProgressBar;
Button4: TButton;
ProgressBar4: TProgressBar;
Button5: TButton;
ProgressBar5: TProgressBar;
procedure Button1Click(Sender: TObject) ;
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
{ TMyThread }
constructor TMyThread.Create(CreateSuspended: Boolean) ;
begin
inherited;
FCounter := 0;
FCountTo := MAXINT;
end;
procedure TMyThread.DoProgress;
var
PctDone: Extended;
begin
PctDone := (FCounter / FCountTo) ;
FProgressBar.Position := Round(FProgressBar.Step * PctDone) ;
FOwnerButton.Caption := FormatFloat('0.00 %', PctDone * 100) ;
end;
procedure TMyThread.Execute;
const
Interval = 1000000;
begin
FreeOnTerminate := True;
FProgressBar.Max := FCountTo div Interval;
FProgressBar.Step := FProgressBar.Max;
while FCounter < FCountTo do
begin
if FCounter mod Interval = 0 then Synchronize(DoProgress) ;
Inc(FCounter) ;
end;
FOwnerButton.Caption := 'Start';
FOwnerButton.OwnedThread := nil;
FProgressBar.Position := FProgressBar.Max;
end;
procedure TMyThread.SetCountTo(const Value: Integer) ;
begin
FCountTo := Value;
end;
procedure TMyThread.SetOwnerButton(const Value: TButton) ;
begin
FOwnerButton := Value;
end;
procedure TMyThread.SetProgressBar(const Value: TProgressBar) ;
begin
FProgressBar := Value;
end;
procedure TMainForm.Button1Click(Sender: TObject) ;
var
aButton: TButton;
aThread: TMyThread;
aProgressBar: TProgressBar;
begin
aButton := TButton(Sender) ;
if not Assigned(aButton.OwnedThread) then
begin
aThread := TMyThread.Create(True) ;
aButton.OwnedThread := aThread;
aProgressBar := TProgressBar(FindComponent(StringReplace(aButton.Name, 'Button', 'ProgressBar', []))) ;
aThread.ProgressBar := aProgressBar;
aThread.OwnerButton := aButton;
aThread.Resume;
aButton.Caption := 'Pause';
end
else
begin
if aButton.OwnedThread.Suspended then
aButton.OwnedThread.Resume
else
aButton.OwnedThread.Suspend;
aButton.Caption := 'Run';
end;
end;
end.
'Delphi > 클래스' 카테고리의 다른 글
쓰레드 추가설명 (0) | 2022.03.23 |
---|---|
익명함수+스레드를 활용한 간단한 스레드 사용 방법 (0) | 2022.01.24 |
델파이 쓰레드(Thread)의 기초 (0) | 2021.08.07 |
델파이 레코드 클래스 성능 비교 (0) | 2021.08.05 |
델파이 TDictionary / TObjectDictionary (0) | 2021.08.04 |
댓글