Delphi-PRAXiS
Seite 4 von 5   « Erste     234 5      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Thread Anfängerfrage (https://www.delphipraxis.net/12179-thread-anfaengerfrage.html)

Spurius 26. Nov 2003 18:05

Re: Thread Anfängerfrage
 
Ok, wenns nicht anders geht, soll ich einfach den code nehmen, den du schonmal gepostet hast?
und was ist da der Unterschied zu meinem? Ich mein, warum sollte das nicht einfrieren?
Gruß
Spurius

choose 26. Nov 2003 18:16

Re: Thread Anfängerfrage
 
Spurius, der von mir gepostete Code war bewusst exemplarisch und kann nicht funktionieren, weil es die Eigenschaft HasData in der Klasse TidTCPClient nicht gibt!
Was Du als "einfrieren" beschreibst, sollte eigentlich ein Abbruch des Kompilerlaufs sein, der Dich auf diese Tatsache aufmerksam macht. In der OH findest Du eine Übersicht der zur Verfügung stehenden Eigenschaften und in einem Buch bestimmt auch Lösungen inkl. Beispiele für viele Grundsatzfragen zu Pascal/Delphi...

Kamil 26. Nov 2003 18:27

Re: Thread Anfängerfrage
 
Der Unterschied liegt vorallem an UpdateMemo, das über Synchronize aufgerufen wird.
In dieser Funktion sollten keine blockierenden Aufrufe (wie z.B. TIdTCPClient.Readln, Sleep) stehen, da der Code nicht im Thread ausgeführt wird zu dem er gehört, sondern im Hauptthread deiner Anwendung, was natürlich deine Anwendung dann einfriert.

Vielelicht hilft dir das ein wenig:
Code:
 läuft im                   läuft im
Hauptthread                 MyThread
     |
     |
     |---->TMyThread.Create---->|
     |                          |
     |                          |
     |                          |
     |                          |
     | |<---Synchronize<--------|
     | |
     | |
     | | Ende von Sync. ------->|
     |                          |
     |                          |
     |                          |
     |                          |
     V                         V
Schau dir mal dieses Tutorial an:
http://www.tutorials.delphi-source.de/threads/

Spurius 26. Nov 2003 18:57

Re: Thread Anfängerfrage
 
Hallo,
könnt ihr mir nicht einfach sagen, wie ich das machen soll?
Wo liegt denn mein Fehler?
Im mainthread oder in mythread?
Gruß
Spurius

Kamil 26. Nov 2003 20:20

Re: Thread Anfängerfrage
 
Wie sieht dein Code vom Thread gerade aus?
Wahrscheinlich ist der Fehler, dass der Code aus dem Thread im Hauptthread ausgeführt wird.
Oder hast du es schon so gemacht wie ich es gepostet habe?

Spurius 27. Nov 2003 12:49

Re: Thread Anfängerfrage
 
Hallo,
das ist meinThreadcode:
Delphi-Quellcode:
unit threadtest;

interface

uses
  Classes,idtcpclient,dialogs,StdCtrls,sysutils;

type
  tmythread = class(TThread)
  private
    fclient:tidtcpclient;
    fmemo:tmemo;
    procedure updatememo;
  protected
    procedure Execute; override;
  public
   constructor create(const aclient: tidtcpclient;
   const amemo: tmemo);

  end;

implementation
uses modul;

constructor tmythread.create(const aclient: tidtcpclient;
         const amemo: tmemo);
begin
 inherited create(true);
 fclient := aclient;
 fmemo := amemo;
 resume;
end;

procedure tmythread.Execute;
begin
 while not terminated do
   if fclient. then     //<- hasdata ???
   synchronize(updatememo)
  else
   sleep(100);
end;


procedure tmythread.updatememo;
begin

 fmemo.Lines.Append(fclient.ReadLn);
end;
end.
Was ist in deinem Code wesentlich anders? Oder was soll ich ändern?
Gruß
Spurius

choose 27. Nov 2003 13:02

Re: Thread Anfängerfrage
 
Das Problem ist, wie Kamil bereits beschrieben hat, dass ReadLn geblockt ist, also die "Programmzeile so lange wartet bis tatsächlich ein String ankommt". Mit Syncronize wechselst Du in den Haupthread, so dass die Idee des Threads, nämlich diese Wartezeit unabhäng vom Hauptthread zu verbringen, untergraben wird...
Bei meiner exemplarischen Darstellung habe ich diesen Effekt durch eine fiktive Methode/Eigenschaft HasData kompensiert, die solange False zurückgibt, bis tatsächlich Daten vorhanden sind, so dass ReadLn niemals warten würde.
Die Schleife
Delphi-Quellcode:
while not Terminated do
  if FClient.HasData then
    Synchronize(UpdateMemo)
  else
    Sleep(100);
entspricht demnach im Wesentlichen einem Polling (tatsächlich nicht wirklich elegant).
Um das Ganze in den Griff zu bekommen, solltest Du innerhalb von Execute eine Exemplar-Variable mit dem Ergebnis von ReadLn füllen und erst anschließend Synchronize aufrufen, also in etwa so
Delphi-Quellcode:
while not Terminated do
begin
  FReceivedString:= FClient.ReadLn;
  Synchronize(UpdateMemo);
end;
Beachte, dass Du innerhalb von UpdateMemo diese Exemplarvariable anstatt FClient verwendest!

Nachteil dieses Ansatzes ist die Tatsache, dass ReadLn per default "unendlich lange" wartet, Du also keine saubere Möglichkeit hast, den Thread zu beenden. Hier könnte ggf doch eine Variante des Pollings verwendet werden, damit zyklisch Terminated abgefragt wird...

Spurius 27. Nov 2003 13:37

Re: Thread Anfängerfrage
 
Hallo,
ich hab nochmal deinen Code hier:
Delphi-Quellcode:
Source:
type
  TMyThreadClass = class(TThread)
  private
    FClient : TSomeClient;
    FMemo : TSomeVCLControl;
    procedure UpdateMemo;
  protected
    s: string;
    procedure Execute;override;
  public
    constructor Create(Host: string; Port: integer; const AMemo: TSomeVCLControl);
  end;


constructor TMyThreadClass.Create(Host: string; Port: integer; const AMemo: TSomeVCLControl);
begin
  inherited Create(True);
  Assert(Assigned(AMemo));

  FClient:= TIdTCPClient.Create(nil);
  FClient.Host:=Host;
  FClient.Port:=Port;
  //copy references to member vars
  FMemo:= AMemo;
  //start thread
  Resume;
end;

procedure TMyThreadClass.Execute;
begin
  try
    FClient.Connect;
    while (not Terminated) and (FClient.Connected) do
    begin
      s:=FClient.Readln;
      Synchronize(UpdateMemo);
    end;
  finally
    FClient.Free;
  end;
end;

procedure TMyThreadClass.UpdateMemo;
begin
  //will be executed within the mainthread
  FMemo.Lines.Append(s);
end;
hier wird ja ein client created, was hat der mit meinem tatsächlichen client im mainthread zu tun?
und wenn ich den create, muss ich ja auch dafür port und host festlegen. aber die werden ja im mainthread über edits festgelegt. wie bekomm ich da werte?
Gruß
Spurius

Kamil 27. Nov 2003 14:56

Re: Thread Anfängerfrage
 
Zitat:

hier wird ja ein client created, was hat der mit meinem tatsächlichen client im mainthread zu tun?
natürlich nichts!
Zitat:

und wenn ich den create, muss ich ja auch dafür port und host festlegen. aber die werden ja im mainthread über edits festgelegt. wie bekomm ich da werte?
die Werte übergibst du mit Hilfe der Parameter von dem Konstruktor.

Zitat:

Nachteil dieses Ansatzes ist die Tatsache, dass ReadLn per default "unendlich lange" wartet, Du also keine saubere Möglichkeit hast, den Thread zu beenden. Hier könnte ggf doch eine Variante des Pollings verwendet werden, damit zyklisch Terminated abgefragt wird...
Das solltest du nicht unbeachtet lassen!!! Schau dir die Parameter von ReadLn an!

choose 27. Nov 2003 15:14

Re: Thread Anfängerfrage
 
Zitat:

Zitat von Kamil
Zitat:

Zitat von choose
Hier könnte ggf doch eine Variante des Pollings verwendet werden, damit zyklisch Terminated abgefragt wird...

Das solltest du nicht unbeachtet lassen!!! Schau dir die Parameter von ReadLn an!

Hallo Kamil,

könntest Du kurz skizzieren, wie Du ohne Polling (sprich: ATimeOut<>IdTimeoutInfinite) den Thread sauber terminierst (if Self.Terminated) und trotzdem jedes Byte von FClient empfängst?


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:45 Uhr.
Seite 4 von 5   « Erste     234 5      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz