![]() |
Mein TThread blockiert die Anwendung
Hallo,
ich möchte eine von mir geschriebenen Klasse im Hintergrund meiner Applikation laufen lassen. Ich möchte diese Klasse aber über Buttons "bedienen" können. Diese Klasse soll dann z.B. einen Labeltext oder andere Dinge verändern. Hier mein Beispielcode, der eigentlich nur dauern den Labeltext von 1 bis 100 ändern soll:
Delphi-Quellcode:
Wenn ich davon in meinem Createereignis des Formulars ein Objekt erzeuge, dann steht die Anwendung - hat jemand einen Tip für mich???
unit UnitThread;
interface uses Classes, ExtCtrls, Windows, StdCtrls; type TMeinThread = class(TThread) private { Private-Deklarationen } Text: TLabel; procedure machen; protected procedure Execute; override; public { Public-Deklarationen } constructor Create(_Text: TLabel); end; implementation uses SysUtils; constructor TMeinThread.Create(_Text: TLabel); begin inherited Create(false); Priority := tpNormal; Text := _Text; end; procedure TMeinThread.Execute; begin while not Terminated do begin Synchronize(machen); end; end; procedure TMeinThread.machen; var i: integer; begin for i := 1 to 100 do begin Text.Caption := IntToStr(i); end; end; end. Gruß und danke, Poolspieler |
Re: Mein TThread blockiert die Anwendung
das ist klar, denn durch synchronize syncronisierst du den Thread mit der Hauptanwendung. Desweiteren macht es keinen Sinn ein Label aus dem Hauptthread (Hauptanwendung) in einem Thread zu verändern außer du würdest zwischendurch noch ein paar berechnungen im Thread anstellen und das Label nur für den Status verwenden.
Letztendlich ist dein ganzer Thread aber überflüssig weil du die gesammte schleife ja syncronisiert durchführst. Sinn würde es nur machen wenn du die Schleife im Thread laufen lässt und nur das setzen der Labelcaption syncronisierst. Dazwischen im Thread am besten noch paar sleeps damit der thread überhaupt sinn macht. |
Re: Mein TThread blockiert die Anwendung
Hi,
vielen Dank für Deine Antwort, die hat mich schon ein gutes Stück weiter gebracht. Mein Beispiel hat jetzt genau das Verhalten, welches ich mir gewünscht habe. Überarbeitetes Beispiel:
Delphi-Quellcode:
Aber ist das wirklich der richtige Weg für so eine Aufgabe?
unit UnitThread;
interface uses Classes, ExtCtrls, Windows, StdCtrls; type TMeinThread = class(TThread) private { Private-Deklarationen } Text: TLabel; i: integer; procedure machen; procedure ausgeben; protected procedure Execute; override; public { Public-Deklarationen } constructor Create(_Text: TLabel); end; implementation uses SysUtils; constructor TMeinThread.Create(_Text: TLabel); begin inherited Create(false); Priority := tpNormal; Text := _Text; end; procedure TMeinThread.Execute; begin while not Terminated do begin machen; end; end; procedure TMeinThread.machen; begin i := 0; while i <= 100 do begin sleep(500); Synchronize(ausgeben); Inc(i); end; end; procedure TMeinThread.ausgeben; begin Text.Caption := IntToStr(i); end; end. Ich habe eine sehr große Klasse geschrieben (aktuell noch OHNE Thread), die sehr viele Berechnungen durchführt und äußerst viele Labels, Charts und andere Bedienelemente aktualisieren bzw. auslesen muss. Diese soll nun auf einen Thread umgestellt werden um ein blockieren der Anwendung zu verhindern (application.processmessages funktioniert nicht so ganz, wie ich mir es vorstelle...) Muss ich nun wirklich für jedes Anzeige- und Bedienelement eine eigene private Variable (hier z.B. das private i:integer) deklarieren? Und dann in einer oder mehreren Methoden die jeweiligen zugehörigen Objekte aktualiseren? Oder gibt es da eine einfachere Elegantere Lösung? Gruß, Poolspieler |
Re: Mein TThread blockiert die Anwendung
du kannst dir ja auch eine ThreadBasisklasse schreiben welche schon die Funktionen zum aktuallisieren eines Labels etc. mitbringt. Und von dieser klasse kannst du ja dann wieder ableiten.
|
Re: Mein TThread blockiert die Anwendung
Zitat:
|
Re: Mein TThread blockiert die Anwendung
Hi,
vielen Dank für eure Antworten und Anregungen. Ich werde halt mein ganzes Projekt umschreiben (was aber wohl erstmal nicht mehr als ca. einen Tag in Anspruch nehmen wird - hoffe ich ;-) ). Wen es interessiert: Ich werde mir ähnlich wie unter Qt (Linux, KDE...) Slots definieren und "Signale" versenden. Es gibt also slotvariablen (boolean) die privat deklariert sind (z.B. mach_mal_was). Diese Slotvariablen kann man mit der Methode SetSignal setzen. In der Execute-Methode frage ich dann zyklisch diese Slotvariablen ab und reagiere dann mit den entsprechenden Funktionen (die dann im Threadkontext verarbeitet werden). Die "Arbeitsmethoden" greifen nicht mehr direkt auf die Anzeigekomponenten (z.B. mit label.capion) zu, sondern speichern den Inhalt der angezeigt werden soll in einer Zustandsvariablen (für jedes Anzeigeobjekt muss ich dann leider eine Zustandsvariable anlegen... naja...). Es gibt dann Aktualisieren-Methoden, die den Inhalt der Zustandsvariablen an die Anzeigeobjekte weiter geben. NUR diese Aktualisieren-Methoden werden noch mit Synchronisize(aktualisiere) aufgerufen. Dann muss man nur noch die Stellen im Code finden, an denen es Sinn macht Daten möglichst gebündelt auszugeben... --> Vielleicht habe ich ja jetzt auch jemandem geholfen, oder eine Anregung gegeben... ;-) Gruß und danke, Poolspieler |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:52 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