Autor Beitrag
Peter18
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Do 29.10.15 18:26 
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


Zuletzt bearbeitet von Peter18 am Mo 02.11.15 19:31, insgesamt 2-mal bearbeitet
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 429
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: Do 29.10.15 19:11 
versuche es einmal mit oStruk.Sync := @Sync
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1321
Erhaltene Danke: 117

Win 10
RIO, CE, Lazarus
BeitragVerfasst: 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;

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
GuaAck
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 376
Erhaltene Danke: 32

Windows 8.1
Delphi 10.4 Comm. Edition
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: 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.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
Type T_Status = record
  Pnl      : TPanel      ;   // Panel auf dem die Fortschrittsanzeige sitzt
  ProgBar  : TProgressBar;   // Balkenanzeige
  Lbl      : TLabel      ;   // Beschreibung der Aktion
end;

Die Ereignisroutine ist folgendermaßen deklariert:

ausblenden 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:

ausblenden Delphi-Quelltext
1:
  Sync : T_Sync;      // Fortschrittsanzeige					

Im Thread werden die Routinen aufgerufen, die die Anzeige sichtbar schalten, Bereiche setzen und den Fortschritt anzeigen.

ausblenden 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 30.10.15 13:50 
Moin!

Ohne im Details alles genau gelesen zu haben, hier möchte ich aber doch was zu sagen:
user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
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

_________________
There are 10 types of people - those who understand binary and those who don´t.
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1321
Erhaltene Danke: 117

Win 10
RIO, CE, Lazarus
BeitragVerfasst: 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.

ausblenden 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; // deine lable, etc.
  FStatus: integer;
  procedure DoUpdateStatus; // die Procedure die den Status anzeigen wird
public
  procedure Exceute; override;
end;


procedure TMyThread.Execute;
begin
  FStatus := 0;
  while not Terminated do
  begin
    Inc(FStatus);
    if FStatus = SchaefchenAmStraßenrand then // irgend ein zustand den der nutzer wissen soll
      Synchronize(DoUpdateStatus); // Procedure im kontext des hauptthreads aufrufen
  end;
end;

procedure TMyThread.DoUpdateStatus;
begin
  FInfoStructure.LableMessage := 'Achtung, bremsen! Sonst hast du gleich ein Schäfchen als Beifahrer.';
  // Du kannst die procedure natürlich auch in anderem kontext aufrufen
  // und dann hier den status oder andere zusätzliche informationen prüfen auswerten.
  // Beispielsweise könnte es sich der Hund des Schäfers ja schon in Deinem Radkasten gemütlich gemacht haben,
  // wodurch jetzt dein Fahrstil beeinflusst wird.
end;

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?

Für diesen Beitrag haben gedankt: Peter18
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: 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:
ausblenden 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:
ausblenden Delphi-Quelltext
1:
oData.Sync := Sync;					

Das ist die Deklaration in der Struktur:
ausblenden Delphi-Quelltext
1:
Sync : T_Sync   ;					

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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1321
Erhaltene Danke: 117

Win 10
RIO, CE, Lazarus
BeitragVerfasst: 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:
ausblenden Delphi-Quelltext
1:
oData.Sync := @Sync; // @ hinzugefügt					


€: Tippfehler behoben.

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?


Zuletzt bearbeitet von Sinspin am Di 03.11.15 17:43, insgesamt 1-mal bearbeitet
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mo 02.11.15 19:22 
Hallo Stefan,

Dank Dir für die Antwort.

Dacht ich brauch das nicht noch mal zu erwähnen:
user profile iconSinspin hat folgendes geschrieben Zum zitierten Posting springen:
wieder das gleiche, wenn Du nicht angibst wie die Fehlermeldung lautet oder was genau passiert kann Dir nur schwehr geholfen werden.

user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
"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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: 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!

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
Type
  T_Sync = procedure ( Act      : T_DispActs;
                       S        : String    ;
                       B        : Boolean   ;
                       Min, Max : Integer     ) of object;

und

ausblenden 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