Ir al contenido


Foto

Sincronizando hilos y GUI


  • Por favor identifícate para responder
1 respuesta en este tema

#1 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 10 marzo 2009 - 08:16

Multi-hilo (multi-threading) en Delphi le permite crear aplicaciones que incluyen varios caminos de ejecución simultánea.

Una aplicación "normal" de Delphi  es un solo hilo de ejecución: todos (VCL) los objetos acceden a sus propiedades y ejecutan sus métodos dentro de este hilo.

Para acelerar el procesamiento de datos en su aplicación, usted puede tomar la decisión de incluir uno o más hilos "secundarios".

Cuando varios subprocesos se ejecutan en la aplicación se plantea la cuestión: cómo actualizar la GUI (interfaz de usuario) como resultado de un hilo de ejecución. La cuestión radica en la clase TThread método Synchronize.

Para actualizar en la aplicación la interfaz de usuario - hilo principal - de un hilo secundario es necesario llamar al método Synchronize - un hilo seguro (thread-safe) que evita el método multi-hilo (multi-threading) los conflictos que pueden surgir a partir de acceder a las propiedades de objetos o métodos que no son del hilo seguro, o utilizando los recursos no en el hilo principal de ejecución.

Un ejemplo de demostración que usa varios botones con barra de progreso, cada barra de progreso muestra el actual "estado" del hilo en ejecución...

Imagen de la pantalla:
Imagen Enviada

Código fuente:


delphi
  1. unit MainU;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, ComCtrls, StdCtrls, ExtCtrls;
  8.  
  9. type
  10.   //interceptor class
  11.   TButton = class(StdCtrls.TButton)
  12.     OwnedThread: TThread;
  13.     ProgressBar: TProgressBar;
  14.   end;
  15.  
  16.   TMyThread = class(TThread)
  17.   private
  18.     FCounter: Integer;
  19.     FCountTo: Integer;
  20.     FProgressBar: TProgressBar;
  21.     FOwnerButton: TButton;
  22.  
  23.     procedure DoProgress;
  24.     procedure SetCountTo(const Value: Integer) ;
  25.     procedure SetProgressBar(const Value: TProgressBar) ;
  26.     procedure SetOwnerButton(const Value: TButton) ;
  27.   protected
  28.     procedure Execute; override;
  29.   public
  30.     constructor Create(CreateSuspended: Boolean) ;
  31.     property CountTo: Integer read FCountTo write SetCountTo;
  32.     property ProgressBar: TProgressBar read FProgressBar write SetProgressBar;
  33.     property OwnerButton: TButton read FOwnerButton write SetOwnerButton;
  34.   end;
  35.  
  36.   TMainForm = class(TForm)
  37.     Button1: TButton;
  38.     ProgressBar1: TProgressBar;
  39.     Button2: TButton;
  40.     ProgressBar2: TProgressBar;
  41.     Button3: TButton;
  42.     ProgressBar3: TProgressBar;
  43.     Button4: TButton;
  44.     ProgressBar4: TProgressBar;
  45.     Button5: TButton;
  46.     ProgressBar5: TProgressBar;
  47.     procedure Button1Click(Sender: TObject) ;
  48.   end;
  49.  
  50. var
  51.   MainForm: TMainForm;
  52.  
  53. implementation
  54.  
  55. {$R *.dfm}
  56.  
  57. { TMyThread }
  58.  
  59. constructor TMyThread.Create(CreateSuspended: Boolean) ;
  60. begin
  61.   inherited;
  62.   FCounter := 0;
  63.   FCountTo := MAXINT;
  64. end;
  65.  
  66. procedure TMyThread.DoProgress;
  67. var
  68.   PctDone: Extended;
  69. begin
  70.   PctDone := (FCounter / FCountTo) ;
  71.   FProgressBar.Position := Round(FProgressBar.Step * PctDone) ;
  72.   FOwnerButton.Caption := FormatFloat('0.00 %', PctDone * 100) ;
  73. end;
  74.  
  75. procedure TMyThread.Execute;
  76. const
  77.   Interval = 1000000;
  78. begin
  79.   FreeOnTerminate := True;
  80.   FProgressBar.Max := FCountTo div Interval;
  81.   FProgressBar.Step := FProgressBar.Max;
  82.  
  83.   while FCounter < FCountTo do
  84.   begin
  85.     if FCounter mod Interval = 0 then Synchronize(DoProgress) ;
  86.  
  87.     Inc(FCounter) ;
  88.   end;
  89.  
  90.   FOwnerButton.Caption := 'Start';
  91.   FOwnerButton.OwnedThread := nil;
  92.   FProgressBar.Position := FProgressBar.Max;
  93. end;
  94.  
  95. procedure TMyThread.SetCountTo(const Value: Integer) ;
  96. begin
  97.   FCountTo := Value;
  98. end;
  99.  
  100. procedure TMyThread.SetOwnerButton(const Value: TButton) ;
  101. begin
  102.   FOwnerButton := Value;
  103. end;
  104.  
  105. procedure TMyThread.SetProgressBar(const Value: TProgressBar) ;
  106. begin
  107.   FProgressBar := Value;
  108. end;
  109.  
  110. procedure TMainForm.Button1Click(Sender: TObject) ;
  111. var
  112.   aButton: TButton;
  113.   aThread: TMyThread;
  114.   aProgressBar: TProgressBar;
  115. begin
  116.   aButton := TButton(Sender) ;
  117.   if not Assigned(aButton.OwnedThread) then
  118.   begin
  119.     aThread := TMyThread.Create(True) ;
  120.     aButton.OwnedThread := aThread;
  121.     aProgressBar := TProgressBar(FindComponent(StringReplace(aButton.Name, 'Button', 'ProgressBar', []))) ;
  122.     aThread.ProgressBar := aProgressBar;
  123.     aThread.OwnerButton := aButton;
  124.     aThread.Resume;
  125.     aButton.Caption := 'Pause';
  126.   end
  127.   else
  128.   begin
  129.     if aButton.OwnedThread.Suspended then
  130.       aButton.OwnedThread.Resume
  131.     else
  132.       aButton.OwnedThread.Suspend;
  133.  
  134.     aButton.Caption := 'Run';
  135.   end;
  136. end;
  137.  
  138. end.



Descarga del código fuente.

P.D. Este articulo no es de mi autoria, hice la traducción y esta es la pagina del autor.
  • 0

#2 joseme

joseme

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 62 mensajes
  • LocationCosta Rica

Escrito 31 marzo 2009 - 08:03

Muchas gracias por tu aporte, Rolphy. En la empresa hemos usado el JvThread, nunca usamos más de un hilo simultáneo. Este fin de semana pienso jugar con este código  :p
  • 0