아래는 '진행'형식 코드의 일부입니다.
(코드에서 제거 된) ProgressBars 외에도 캡션 (점의 수가 증가)을 변경하려는 TLabel (LblDots)이 있습니다.
FormShow/FormClose에서 TDotterThread가 만들어지고 소멸됩니다.
열려있는 넌 모달 형식에서 스레드가 실행되지 않음
문제 :
나는 프로그램이 무거운 일을하지 않을 경우에만 호출되는 라벨을 업데이트하는 동기화 (DoUpdate) 절차를 참조하십시오. 내가 잘못 뭐하는 거지
procedure TFrmTest.FormCreate(Sender: TObject);
begin
FFormBusy := TFormBusy.Create(nil);
end;
procedure TFrmTest.FormDestroy(Sender: TObject);
begin
FFormBusy.Free;
end;
procedure TFrmTest.BtnCompareClick(Sender: TObject);
begin
FrmTest.FFormBusy.ShowDots := true;
FrmTest.FFormBusy.Show;
FrmTest.FFormBusy.Update label/progress bar
DoHeavyWork1();
FrmTest.FFormBusy.Update label/progress bar
DoHeavyWork2();
etc.
end;
:
unit FrmBusy;
interface
uses
System.SyncObjs, Windows, Messages, SysUtils, System.Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type
TUpdateEvent = procedure of object; // 'of object' to prevent 'Incompatible types: regular procedure and method pointer'
type
TDotterThread = class(TThread) // Thread to update LblDots
private
FTick: TEvent;
FUpdater: TUpdateEvent;
protected
procedure Execute; override;
procedure DoUpdate;
public
constructor Create;
destructor Destroy; override;
property Updater: TUpdateEvent read FUpdater write FUpdater;
procedure Stop;
end;
type
TFormBusy = class(TForm)
LblDots: TLabel;
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
FShowDots: Boolean;
FDotterThread: TDotterThread;
procedure UpdateDots;
public
property ShowDots: Boolean write FShowDots;
end;
implementation
{$R *.DFM}
procedure TFormBusy.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if FShowDots then FDotterThread.Stop; // Calls Terminate and is FreeOnTerminate
end;
procedure TFormBezig.UpdateDots;
var s: String;
begin
s := LblDots.Caption;
if Length(s) = 50 then s := '' else s := s + '.';
LblDots.Caption := s;
Application.ProcessMessages;
end;
procedure TFormBusy.FormShow(Sender: TObject);
begin
LblDots.Caption := '';
if FShowDots then
begin
FDotterThread := TDotterThread.Create;
FDotterThread.Updater := Self.UpdateDots;
FDotterThread.Start;
end;
BringWindowToTop(Self.Handle);
end;
{ TDotterThread }
constructor TDotterThread.Create;
begin
FTick := TEvent.Create(nil, True, False, '');
FreeOnTerminate := true;
inherited Create(true); // Suspended
end;
destructor TDotterThread.Destroy;
begin
FTick.Free;
inherited;
end;
procedure TDotterThread.DoUpdate;
begin
if Assigned(FUpdater) then FUpdater;
end;
procedure TDotterThread.Execute;
begin
while not Terminated do
begin
FTick.WaitFor(1000);
Synchronize(DoUpdate);
end;
end;
procedure TDotterThread.Stop;
begin
Terminate;
FTick.SetEvent;
end;
end.
양식은 전화를 같이 작성됩니다
이 진행 형태이다?
TIA
DoUpdate는 동기화되어야하기 때문에 메인 스레드의 컨텍스트에 있고 메인 스레드에 "유휴 시간"이있는 경우에만 업데이트 절차를 처리 할 수 있습니다. 어쩌면 스레드 내에서 DoHeavyWorkx를 처리하도록 변경할 수 있습니다. – bummi
@bummi는 정확합니다. 메소드를 동기화하여 주 스레드로 다시 밀어 넣고 전체 목적을 물리칩니다.우리에게 보여줄 수있는 중요한 절차, 그리고 수정해야 할 절차는'FFormBusy.UpdateDots'라고 생각합니다 - 그 코드를 게시 할 수 있습니까? (더 많은 점 ... 더 많은 점을 보여라!) –
@J 나는 코드에서 그것을 accidenttaly 잘라내는 것을 본다 - 그것을 수정하기 위해 나의 질문을 편집했다. –