zoukankan      html  css  js  c++  java
  • Synchronizing Threads and GUI in Delphi application

    Synchronizing Threads and GUI

    Synchronizing Threads and GUI

     
     
    Code submitted by Jens Borrisholt

    Multi-threading in Delphi lets you create applications that include several simultaneous paths of execution.

    A "normal" Delphi application is single-threaded: all (VCL) objects access their properties and execute their methods within this single thread.

    Threads and GUI

    To speed up data processing in your application you can decide to include one or more "secondary" threads.

    When several threads are running in the application a question arises: how to update your GUI (user interface) as a result of a thread execution. The question lies in the TThread class Synchronize method.

    To update your application's user interface - main thread - from a secondary thread you need to call the Synchronize method - a thread-safe method that avoids multi-threading conflicts that can arise from accessing object properties or methods that are not thread-safe, or using resources not in the main thread of execution.

    An example demo uses several buttons with progress bar, each progress bar displaying the current "state" of the thread execution...

    Download source code

    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.
  • 相关阅读:
    SendMessage操作另一个EXE,存在这,以后也许用得着。
    六、Delphi 2009 泛型容器单元(Generics.Collections)[5]: TObject...<T> 系列
    闲扯原码、反码、补码
    限制edit只能输入数字
    动态创建TXMLDocument对XML文件进行读取和写入
    XML操作
    Ubuntu下配置lazarus开发环境
    C#结构体(二)
    【转】 如何有效減少Nios II EDS所編譯程式碼大小? (IC Design) (Nios II)
    关于NiosII和Win7系统兼容性的问题处理方式
  • 原文地址:https://www.cnblogs.com/shuaixf/p/3515192.html
Copyright © 2011-2022 走看看