![]() |
Update eines Labels aus einer Verarbeitungsschleife
Hallo zusammen,
die meisten Programme, die ich schreibe, beschäftigen sich damit, Dateien zu lesen, die Daten zu verarbeiten und wieder neue Dateien zu schreiben. Da diese Dateien oft etwas größer als 100 MB sind, dauert die Verarbeitung auch etwas. Dann ist es kein Fehler den Benutzer über einen Satzzähler oder einen Fortschritsbalken oä zu informieren. Da ich versuche die Verarbeitungsschritte von der Oberfläche zu trennen habe ich das Problem den Zähler an die Oberfläche zu übergeben. Bisher habe ich zwei Wege beschritten: a) Mit Hilfe des Timers lese ich eine Zählervariable in der Verarbeitungsunit aus, b) Ich übergebe ein Label/Fortschrittbalken an die Verarbeitungsroutine. Ist der Wert des Labels <> nil dann wird der Zähler ausgegeben. Beide Wege funktionieren. Nun hätte ich gerne einen Tip wie ich ohne großen Overhead Oberfläche und Verarbeitung stärker entkoppeln kann. Wichtig ist daß die meiste Rechenzeit wirklich für die Verarbeitung und nicht für die Oberfläche genutzt wird. Vielen Dank im voraus K-H |
Re: Update eines Labels aus einer Verarbeitungsschleife
ich würde die Verarbeitung in einen Thread auslagern und von diesem per PostMessage ab und zu eine Statusmeldung an den Hauptthread schicken.
|
Re: Update eines Labels aus einer Verarbeitungsschleife
Hall,
was ist denn an b) so verkehrt? Ähnlich mache ich es auch. Heiko |
Re: Update eines Labels aus einer Verarbeitungsschleife
@Sir Thornberry
Da schreckt mich etwas der Aufwand (naja ich bin ein Datenschafler und von Threads habe ich keine praktische Ahnung) @hoika zum einen schleppe ich mir über das uses vollkommen überflüssige units in die verarbeitung ein, zum anderen steuere ich innerhalb der Verarbeitung noch die Oberfläche. Das ist sicher besser als "Man sieht, das man nichts sieht, also arbeitet er" aber die reine Lehre ist das nicht. Was meinst Du was ich geflucht habe als ich TP-Programme nach Delphi portiert habe. Da ist die Methode a) schon etwas wartungsfreundlicher weil das meiste innerhalb der Unit abläuft. Nur Fragst Du dich manchmal "wofür brauch ich eigentlich 'Zähler'". erst einmal vielen Dank für Eure Reaktion K-H |
Re: Update eines Labels aus einer Verarbeitungsschleife
Moin, moin,
Oft habe ich zur Datenausgabe eine Variable vom Typ TStringList definiert. Die wird im Programm zunächst der Lines Eigenschaft eines TMemos oder TRichEdits zugewiesen. In den Routinen schreibe ich dann Hinweise in meine LokalStringList die in meinen Routinen fest verankert ist. Dadurch brauche ich kein visuelles Objekt in den Rechenroutinen und habe zudem eine mehrzeiliga Ausgabe. Grüße // Martin |
Re: Update eines Labels aus einer Verarbeitungsschleife
Zitat:
HTH, Uli. |
Re: Update eines Labels aus einer Verarbeitungsschleife
Die Verarbeitung in einen Thread auslagern, der Threadklasse das GUI Fensterhandle überreichen und dann mit Messages arbeiten dürfte der generischste und entkoppelteste Weg sein, den du erreichen kannst. Dabei steht dir dann u.a. auch frei, ob und welche Messages du überhaupt nachher anzeigen lassen willst, und in welcher Form (Text, Gauge, Balken etc.).
Noch weiter gedacht, könnte man sich vorstellen, dass man mehrere Fenster(handles) in der Threadklasse hinterlegt, so dass evtl. sogar jeder Signaltyp (wenn man mal mehr als nur einen Counter hat) theoretisch an ein anderes Fenster gesendet werden kann. Damit könnte man dann sogar realisieren, dass eine von TEdit abgeleitete Klasse selbst auf eine Message aus dem Thread reagiert und die Anzeige übernimmt, ohne dass in einem zentralen Formular eine Verteilungslogik her müsste. Einfach direkt an diese Klasse senden lassen. Ich denke schon, dass es sich langfristig sehr lohnen würde, sich mit Threads zu beschäftigen. Viele machen sich bei dem Thema auch oft zu viel in die Hose; es ist wirklich nicht kompliziert, wird aber wie so oft heuertage durch eine ganz tolle hochtrabende Begriffswelt verklausuliert, die erstmal nur erdrückend aussieht. Die Konzepte hinter Synchronizing, Locking, Priority, WaitForSingleObject und so weiter sind an sich recht trivial - zumindest wenn man nicht grad letzte Woche seinen ersten Compiler gekauft hat ;) |
Re: Update eines Labels aus einer Verarbeitungsschleife
Hallo zusammen,
danke für Eure Tips, da ist das Wochenende ja gerettet. Ich werde das alles mal ausprobieren, vielleicht sind Threads ja wirklich DIE Lösung! viele Grüße und ein schönes Wochenende K-H |
Re: Update eines Labels aus einer Verarbeitungsschleife
Zitat:
|
Re: Update eines Labels aus einer Verarbeitungsschleife
Und wenn die den Overhead eines Thread vermeiden willst, ruf in der Schleife regelmäßig, aber nicht zu oft, Application.ProcessMessages auf. Dieser Aufruf veranlasst das Fenster seine Nachrichtenschleife abzuarbeiten. dies hat eben auch zur Folge, dass dein Label aktualisiert wird.
|
Re: Update eines Labels aus einer Verarbeitungsschleife
Hallo Zusammen,
auch wenn es etwas her ist, habe ich trotzdem vor mich hingebastelt. Folgende Lösung scheint recht tauglich zu sein:
Delphi-Quellcode:
{-- Diese Procedure koppelt die Anzeige im Form und den Counter in der Daten-Unit } procedure CNT_ANZEIGE(instr:string); begin form1.Label1.Caption:=instr; {ein String kann auch mehr sein als eine Zahl } application.ProcessMessages; {sonst gibts keine Anzeige } end; procedure TForm1.Button1Click(Sender: TObject); var starttime, endtime : tdatetime; begin starttime:=now; READ_DATA('c:\temp\paend.txt'); endtime:=now; form1.Label2.Caption:='Laufzeit: '+timetostr(endtime-starttime)+' HH:MM:SS'; end; procedure TForm1.FormCreate(Sender: TObject); begin SHOWCNT:=CNT_ANZEIGE; end;
Delphi-Quellcode:
Der besondere Charme liegt meiner Meinung darin, daß die Daten-Unit nicht weiß ob sie in einer Consolen oder Windowsanwendung läuft. Falls die Kopplungsprozedur zugewiesen wurde, wird nur ein String übergeben der von der Oberflächen Unit verarbeitet wird oder nicht.
interface
var SHOWCNT: procedure (instr:string); procedure READ_DATA(efile:string); implementation uses sysutils; procedure READ_DATA(efile:string); var tdat : textfile; cnt : integer; dummy : string; begin cnt:=0; assignfile(tdat,efile); reset(tdat); repeat readln(tdat,dummy); inc(cnt,1); if cnt and $F=0 then { damit die Ausgabe nicht zu oft aufgerufen wird } if assigned(SHOWCNT) then { läuft auch wenn in der Form-Unit keine Anzeige/Ausgabe erfolgt} SHOWCNT(inttostr(cnt)); until eof(tdat); closefile(tdat); end; end. Ist Sie nicht zugewiesen, stört das die Daten-Unit überhaupt nicht, sie ist also volkommen unabhängig von der Oberflächen-Unit. Darum habe ich das TNotifyEvent auch nicht benutzt, da dann auf jeden Fall eine OO-Oberfläche vorhanden sein muß und ich wollte mir alle Optionen offen halten. Die Einbindung in das Form ist nicht optimal, erfüllt aber seinen Zweck. Den Lösungsansatz mit Threads werde ich mal aufgreifen wenn ich richtig fette Dateien zu lesen habe. Vielen Dank nochmal für Eure Tips und Anregungen. Grüße K-H |
Re: Update eines Labels aus einer Verarbeitungsschleife
Zitat:
|
Re: Update eines Labels aus einer Verarbeitungsschleife
Hallo Uli,
ich hab im Augenblick gut zu tun, darum reagiere ich etwas langsam. Leider verstehe ich Deine Einlassungen nicht. Wenn ich mich richtig erinnere beinhaltet TNotifyEvent zwei Adressen, die der Routine und die des besitzenden Objektes, da ich aber von OO unabhängig sein will ,was nicht deckungsgleich mit VCL ist, habe ich diese "Sparversion" gewählt. Das Callback verstehe ich überhaupt nicht. Die Anzeige ist ja nur nettes Beiwerk für den Benutzer. Die eigentliche Verarbeitung soll ja davon vollkommen unberührt sein. Der ist es egal ob eine Anzeige erfolgt. Gruß K-H |
Re: Update eines Labels aus einer Verarbeitungsschleife
Morgen, K-H!
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
Das ist aber alles Geschmackssache, also ignoriere meinen "Senf", wenn deine Lösung funktioniert. :mrgreen:
procedure CNT_ANZEIGE(instr:string; Data: Pointer);
begin TForm1(Data).Label1.Caption:=instr; {ein String kann auch mehr sein als eine Zahl } application.ProcessMessages; {sonst gibts keine Anzeige } end; Uli. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:17 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