![]() |
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 |
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... |
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:
Schau dir mal dieses Tutorial an:
läuft im läuft im
Hauptthread MyThread | | |---->TMyThread.Create---->| | | | | | | | | | |<---Synchronize<--------| | | | | | | Ende von Sync. ------->| | | | | | | | | V V ![]() |
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 |
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? |
Re: Thread Anfängerfrage
Hallo,
das ist meinThreadcode:
Delphi-Quellcode:
Was ist in deinem Code wesentlich anders? Oder was soll ich ändern?
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. Gruß Spurius |
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:
entspricht demnach im Wesentlichen einem Polling (tatsächlich nicht wirklich elegant).
while not Terminated do
if FClient.HasData then Synchronize(UpdateMemo) else Sleep(100); 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:
Beachte, dass Du innerhalb von UpdateMemo diese Exemplarvariable anstatt FClient verwendest!
while not Terminated do
begin FReceivedString:= FClient.ReadLn; Synchronize(UpdateMemo); end; 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... |
Re: Thread Anfängerfrage
Hallo,
ich hab nochmal deinen Code hier:
Delphi-Quellcode:
hier wird ja ein client created, was hat der mit meinem tatsächlichen client im mainthread zu tun?
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; 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 |
Re: Thread Anfängerfrage
Zitat:
Zitat:
Zitat:
|
Re: Thread Anfängerfrage
Zitat:
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. |
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