Announcement

Collapse
No announcement yet.

Probleme Synchronize

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Probleme Synchronize

    Hallo,<br>ich habe ein Problem mit Synchronize. Wenn ich im untenstehenden Quelltext in der Execute Methode Synchronize verwende, werden die beiden Labels nicht parallel hochgezählt. Ohne Synchronize läuft es parallel. Mir ist aber klar, dass ich die Sache synchronizieren muß. Kann mir jemand erklären, warum es mit Synchronize nicht parallel läuft ?<br>:-) Jens Schumann
    <pre><font face="Verdana" size="2">
    unit Unit1;
    interface
    uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    StdCtrls, syncobjs;
    type
    TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
    private
    { Private-Deklarationen }
    procedure CountingLabel(aLabel : TLabel);
    public
    { Public-Deklarationen }
    end;
    TThreadTest = class(TThread)
    private
    { Private-Deklarationen }
    FForm : TForm1;
    FLabel : TLabel;
    procedure CountLabel;
    protected
    constructor Create(CreateSuspended : Boolean;aForm : TForm1;aLabel : TLabel);
    procedure Execute; override;
    end;
    var Form1: TForm1;
    implementation
    {$R *.DFM}
    { TForm1 }
    procedure TForm1.CountingLabel(aLabel: TLabel);
    var
    iCnt : Integer;
    begin
    For iCnt:=0 to 5000 do
    begin
    aLabel.Caption:=IntToStr(iCnt);
    Application.ProcessMessages;
    end;
    end;
    { TThreadTest }
    procedure TThreadTest.CountLabel;
    begin
    FForm.CountingLabel(FLabel);
    end;
    constructor TThreadTest.Create(CreateSuspended: Boolean; aForm: TForm1;aLabel : TLabel);
    begin
    Inherited Create(CreateSuspended);
    FForm:=aForm;
    FLabel:=aLabel;
    FreeOnterminate:=True;
    Resume;
    end;
    procedure TThreadTest.Execute;
    begin
    // Synchronize(CountLabel);
    CountLabel;
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    var
    aThreadTest : TThreadTest;
    begin
    aThreadTest:=TThreadTest.Create(True,Self,Label1);
    aThreadTest:=TThreadTest.Create(True,Self,Label2);
    end;
    end.</font></pre>

  • #2
    Hallo,

    bei der o.g. Implementierung wird zwar die Methode <b>CountingLabel</b> von unterschiedlichen Threads aus aufgerufen, aber immer nur in einem Thread (dem primären Thread der VCL) ausgeführt, wenn <b>Synchronize</b> verwendet wird.

    In meinem Buch <i>Delphi Win32-Lösungen</i> gehe ich intensiver auf die Zusammenhänge ein. Hier nur die Kurzfassung: Synchronize schickt die Botschaft <i>CM_ExecProc</i> an das Hauptfenster (primärer Thread), wobei die auszuführende Methode als Adress-Parameter (<i>lParam</i>) indirekt übergeben wird. Wenn der primäre Thread diese Botschaft verarbeitet, führt er die übergebene Methode (...<i>with TThread(lParam) do FMethod...</i>) über die Adresse im eigenen Thread aus. Da es nun einen primären Thread geben kann, bedeutet dies zwangsläufig, dass immer nur ein Aufrufthread "zum Zuge" kommt.

    Man muss also dafür sorgen, dass die parallel abzuarbeitenden Arbeitsschritte auch tatsächlich in der TThread-Methode <b>Execute</b> abgearbeitet werden und nur die "visuellen Ergebnisse" an das Hauptformular (primärer Thread) weitergereicht werden, indem man <br>
    a) entweder Synchronize aufruft, oder <br>
    b) eine private Botschaft über <b>PostMessage</b> an das Hauptfenster schickt und die Daten in den Botschaftsparametern verpackt, oder <br>
    c) usw.
    &#10

    Comment


    • #3
      Hallo Herr Kosch,
      ich habe in Ihr Win32-Lösungen Buch geschaut und bin fündig geworden.
      Siehe Seite 327 und 328. Jetzt läuft es so, wie ich es mit vorgestellt habe.<br>Vielen Dank<br>:-) Jens Schuman

      Comment

      Working...
      X