Entwickler-Ecke
Sonstiges (Delphi) - Ereignisroutine im Thread zum Synchronisieren einer Anzeige?
Peter18 - Do 29.10.15 18:26
Titel: Ereignisroutine im Thread zum Synchronisieren einer Anzeige?
Ein freundliches Hallo an alle,
ich möchte folgendes tun:
Lesen und Auswerten von Daten soll in einem Tread laufen, damit der Rest der Anwendung bedienbar bleibt. Da aber unterschiedliche Opperationen auszuführen sind, habe ich die Routinen in ein anderes Modul geschrieben. Auch die Schleifen, in denen die Opperationen ablaufen befinden sich dort.
Muß die Anzeige für den Fortschritt der Opperation über die "Thread.Synchronize" laufen, oder kann das direkt in den ausführenden Routinen erfolgen?
Wenn die Anzeige für den Fortschritt der Opperation über die "Thread.Synchronize" laufen muß, wie kann ich das machen, Ein Versuch eine Ereignisroutine in eine Datenstruktur einzutragen führte zu Fehlern.
"Sync : T_Sync;" ist die Deklaration in der Strukrur. Beim Zuweisen "oStruk.Sync := Sync;" werden auch die Parameter erwartet. Wie muß ich die Ereignisroutine zuweisen? Oder geht er auch einfacher??
Grüße von der heute unter Hochnebel liegenden Nordsee
Peter
mandras - Do 29.10.15 19:11
versuche es einmal mit oStruk.Sync := @Sync
Peter18 - Do 29.10.15 19:27
Hallo mandras,
Dank für die Antwort. Leider kommt dann die Meldung "Variable erforderlich".
Grüße von der Nordsee
Peter
Sinspin - Do 29.10.15 20:02
Dann zeig mal bitte etwas Quelltext. Also, wie sieht die Deklaration für den Typ aus und wie die der Procedure;
GuaAck - Do 29.10.15 23:15
Hallo Peter18,
a) Du schreibst zu Deinem Hauptform eine Methode "Zeige_Bearbeitungstand", die Du dann von Deinem Rechenthread mit synchronize aufrufst. Nachteil: Wenn Dein Hauptthread gerade zu tun hat, dann wartet Dein Rechenthread. Vorteil: Klarer Ablauf
b) Wie a) aber ohne Synchronize. Das ist nicht korrekt, geht aber meistens.
c) Mit PostMessage eine Nachricht an den Hauptthread schicken, in der der Baerbeitungsfortschritt übermittelt wird und dann mit einer Methode wie a) (ON Message...) angezeigt. Trotz etwas Aufwand (gering) mit der Einrichtung der Message ist das mein Favorit. Risiko: Wenn der Rechenthread mehr Messages erzeugt als der Hauptthread anzuzeigen schafft, dann gibt es Chaos. Ist aber leicht schätzbar...
Gruß
GuaAck
Peter18 - Fr 30.10.15 13:37
Hallo Stefan, hallo GuaAck,
Dank Euch für die Antworten! Da die Routinen über diverse Verzweigungen angesteuert werden versuche ich mich auf das Kernproblem zu beschränken.
Wenn ich GuaAck richtig verstanden habe kann es ohne "Thread.Synchronize" funktionieren, aber darüber ausgeführt ist es sicher?
Zur Anzeige des Beatbeitungszustandes verwende ich ein Paneel mit Label und ProgressBar. Die Elemente werden in einer Teilstruktur eingetragen und an den Thread in der Gesamtstruktur übergeben.
Delphi-Quelltext
1: 2: 3: 4: 5:
| Type T_Status = record Pnl : TPanel ; ProgBar : TProgressBar; Lbl : TLabel ; end; |
Die Ereignisroutine ist folgendermaßen deklariert:
Delphi-Quelltext
1: 2: 3: 4: 5:
| Type T_Sync = procedure ( Act : T_DispActs; S : String ; B : Boolean ; Min, Max : Integer ) of object; |
In der Gesamtstruktur ist diese Routine so eingetragen:
Im Thread werden die Routinen aufgerufen, die die Anzeige sichtbar schalten, Bereiche setzen und den Fortschritt anzeigen.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| procedure Data_Thread.Synchronize( Act : T_DispActs; Status : T_Statust; S : String; B : Boolean; Min, Max : Integer ); begin if Act = aRan then DspActSet ( LdCont, Min, Max ); if Act = aAct then DspAction ( LdCont, S, B ); if Act = aStep then DspActStep( LdCont ); end; |
Das Hauptformular ist die Bedienoberfläche, in der auch die Fortschrittsanzeige sitzt. Ohne Thread funktioniert ea einwandfrei, aber bei größeren Datenmengen wäre die Bedienung blockiert, daher der Thread.
Im
"Data_Thread.Execute;" wird die Ereignisroutine zugewiesen und dabei wird der Fehler gemeldet:
Delphi-Quelltext
1:
| oData.Sync := Synchronize; |
Meine Fragen:
Data_Thread.Synchronize sollte unbedingt benutzt werden?
Warum werden Parameter verlangt, obwohl eine Ereignisroutine deklariert ist? Hab' ich da was übersehen?
Grüße von der sonnigen Nordsee
Peter
Narses - Fr 30.10.15 13:50
Moin!
Ohne im Details alles genau gelesen zu haben, hier möchte ich aber doch was zu sagen:
Peter18 hat folgendes geschrieben : |
Wenn ich GuaAck richtig verstanden habe kann es ohne "Thread.Synchronize" funktionieren, aber darüber ausgeführt ist es sicher?
[...]
Data_Thread.Synchronize sollte unbedingt benutzt werden? |
Die VCL ist nicht threadsafe! Das ist ein Fakt, Aussagen wie "kann man machen, meistens funktioniert´s" kann ich nicht nachvollziehen. :nixweiss:
Wenn man aus einem anderen Thread (als dem "Mainthread" der Anwendung) heraus auf VCL-Komponenten zugreifen möchte, dann MUSS das synchronisiert erfolgen (technisch gesprochen an den MainThread delegiert werden). Macht man das nicht, ist das Verhalten der Anwendung UNDEFINIERT, es kann von "Absturz" bis "nix" alles passieren. Dieses Risiko sollte kein professioneller Anwendungsentwickler bewusst eingehen - das wollen wir doch hier nicht wirklich diskutieren, oder? :suspect:
cu
Narses
Peter18 - Fr 30.10.15 14:07
Hallo Narses,
Dank auch Dir. Ich wollte mich in dieser Hinsicht nur vergewissern, da das, was ich an Informationen zu Delphi 4 habe sehr dürftig ist. Durch Deine Antwort kenne ich jetzt die Zusammenhänge! Zuvor war alles etwas vage. Da ich jetzt anfange mit Treads zu arbeiten, möchte ich mich nicht schon am Anfang aufs Glatteis begeben!
Grüße von der noch immer sonnigen Nordsee
Peter
Sinspin - Sa 31.10.15 12:48
Hallo Peter,
Du versuchst die Methode Synchronize im Thread zu überscheiben (oder zu überdecken). Das ist aber nicht der Sinn selbiger.
Du brauchst Synchronize für den Aufruf, aber schreiben was ausgeführt werden soll schreibst Du in einer parameterlosen Procedure.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| TMyThread=class(TThread) private FInfoStructure: TInfoStructure; FStatus: integer; procedure DoUpdateStatus; public procedure Exceute; override; end;
procedure TMyThread.Execute; begin FStatus := 0; while not Terminated do begin Inc(FStatus); if FStatus = SchaefchenAmStraßenrand then Synchronize(DoUpdateStatus); end; end;
procedure TMyThread.DoUpdateStatus; begin FInfoStructure.LableMessage := 'Achtung, bremsen! Sonst hast du gleich ein Schäfchen als Beifahrer.'; end; |
Peter18 - Mo 02.11.15 16:07
Hallo Stefan,
Dank Die für Deine Klarstellung! Hab alles entsprechend umgebaut aber ein Problem bleibt. Warscheinlich eine Kleinigkeit aber ich sehe sie nicht.
Die Bearbeitung der Daten findet, der Übersichtlichkeit halber in anderen Units statt. "Exceute" ruft eine Routine in einer anderen Unit auf. Je nach dem welche Daten wie bearbeitet werden sollen, werden weitere Units bemüht. Die Schleifen, in denen die Daten bearbeitet werden liegen demnach in den anderen Units.
Um die Fortschrittsanzeige zu aktualisieren hatte ich an eine Ereignisroutine gedacht, die in der Struktur eingetragen und in der Schleife der Bearbeitungsroutine aufgerufen wird.
Das ist die Ereignisroutine:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure Data_Thread.Sync( Act : T_DispActs; Status : T_Statust; S : String; B : Boolean; Min, Max : Integer ); begin oAct := Act ; oLdCont := LdCont; oS := S ; oB := B ; oMin := Min ; oMax := Max ; Synchronize( DoSync ); end; |
Beim Zuweisen der Routine in "Data_Thread.Execute;" tritt der Fehler auf:
Das ist die Deklaration in der Struktur:
An der Type-Deklaration der Procedur hat sich nichts geändert.
Mache ich hier einen Denkfehler oder habe ich irgendwo einen Fehler eingebaut?
Grüße von der Nebligen Nordsee
Peter
Sinspin - Mo 02.11.15 17:13
Hallo Peter,
wieder das gleiche, wenn Du nicht angibst wie die Fehlermeldung lautet oder was genau passiert kann Dir nur schwehr geholfen werden.
Solange Sync von einem
procedure of object typ ist, sehe ich erstmal keine Probleme mit einer Zuweisung. Habe ich schon x-mal gemacht. Allerdings in D7++, kann sein dass das in D4 noch nicht möglich ist.
versuch es mal so:
€: Tippfehler behoben.
Peter18 - Mo 02.11.15 19:22
Hallo Stefan,
Dank Dir für die Antwort.
Dacht ich brauch das nicht noch mal zu erwähnen:
Sinspin hat folgendes geschrieben : |
wieder das gleiche, wenn Du nicht angibst wie die Fehlermeldung lautet oder was genau passiert kann Dir nur schwehr geholfen werden. |
Peter18 hat folgendes geschrieben : |
"Sync : T_Sync;" ist die Deklaration in der Strukrur. Beim Zuweisen "oStruk.Sync := Sync;" werden auch die Parameter erwartet. Wie muß ich die Ereignisroutine zuweisen? Oder geht er auch einfacher?? |
Es macht keinen Unterschied, ob ein "@" davor steht oder nicht. Ich habe an anderen Stellen auch schon Ereignisroutinen erstellt, und keine Probleme damit gehabt. Deshalb stehe ich im Moment im Wald.
Grüße von der noch immer nebligen Nordsee
Peter
Peter18 - Mi 04.11.15 13:31
Ein freundliches Hallo an alle,
da kann man noch so lange drauf gucken, man sieht immer das, was da stehen soll! Wenn man es aber lange genug schmoren, läßt erkennt man was da wirklich steht!
Delphi-Quelltext
1: 2: 3: 4: 5:
| Type T_Sync = procedure ( Act : T_DispActs; S : String ; B : Boolean ; Min, Max : Integer ) of object; |
und
Delphi-Quelltext
1: 2:
| procedure Data_Thread.Synchronize( Act : T_DispActs; Status : T_Statust; S : String; B : Boolean; Min, Max : Integer ); |
unterscheiden sich! "Status : T_Statust;" macht den Unterschied! Statt über fehlende Parameter zu meckern hätte ein Hinweis darauf, dass eine procedure keine Ergebnis liefert, schneller zum Ziel geführt,
oder auch nicht. Die Parameter hatte ich verglichen ... siehe oben!
Grüße von der heute sonnigen Nordsee
Peter
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!