Synchronizing Threads and GUI in Delphi application

16330 단어 application
Synchronizing Threads and GUI


 


//
zSB(3,3)

//]]>

See More About

  • delphi multithreading
  • tthread class
  • user interface design




  •  


    //
    zSB(1,2);if(zs<3){gEI('sp2').className=gEI('sb2').className='hide';}

    //]]>


    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.

     





    Suggested Reading

  • Threading in Delphi
  • Multithreaded Delphi Database Queries
  • Folder (Subdirectory) SIZE


  • //
    w('')

    //]]>


    New posts to the
    Delphi Programming forums :


  • Advanced editing - TadpEdit component
  • Rotate bits
  • code conversion technique




  • Related Articles


  • Most Recently Used (MRU) menu component - TadpMRU - full source code
  • How To Create a Word Wrapped TButton
  • TDBButton - data aware TButton control
  • DictionaryBase class (Delphi for .NET example)
  • TColorButton - button with color properties - full source code






  • //
    zSB(3,3)

    //]]>
    //
    if(z336>0){w('

    Advertisement

    ');adunit('','','about.com',ch,gs,300,250,' 1','bb',3);w('
    ')}if(z155>0){w('

    Advertisement

    ');adunit ('','','about.com',ch,gs,336,155,'1','ps',4);w('
    ')}

    //]]>

     


    //
    if(zSbL<1)zSbL=3;zSB(2);zSbL=0

    //]]>

    좋은 웹페이지 즐겨찾기