Autor Beitrag
BattleFrog
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 53

WIN 2000
Delphi 7 Ent.
BeitragVerfasst: Mi 18.01.06 17:12 
Ich habe folgenden Code:

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:
TServer = class
  FTCPServer: TIdTCPServer;
  ...
private
  procedure HandleOnExecute(AThread: TIdPeerThread);
  procedure Foo;
  ...
end;

...
FTCPServer.OnExecute := HandleOnExecute;
...

procedure TServer.HandleOnExecute(AThread: TIdPeerThread);
begin
  Foo;
end;

procedure TServer.Foo;
begin
  ...
end;


Ist diese Konstuktion Thread sicher, oder ist der Aufruf von Foo ein Fehler, der bei gleichzeitigen OnExecute Ereignissen ne Exception verursacht?

Wie kann ich aus der OnExecute korrekt Proceduren aufrufen?
UGrohne
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Mi 18.01.06 21:13 
Mit dem jetzgen Code ist der Aufruf thread-safe, da du in foo ja nichts machst. Jetzt kommt es darauf an, was Du dort genau machst. Wenn Du z.B. globale Variablen verwendest, dann musst Du mit Hilfe einer Critical Section gleichzeitige Zugriffe verhindern.
BattleFrog Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 53

WIN 2000
Delphi 7 Ent.
BeitragVerfasst: Do 19.01.06 13:38 
Also in der Foo (Is ja nur ein Beispiel) wird eine Ereignisprozedur aufrufen, um dem Hauptthread (GUI) ein Ereignis zu melden, das zum Update einiger GUI-Elemente führt.

Und es hat sich in einem Test als garnicht sicher rausgestellt :)

CriticalSection hat erstmal zu keiner Verbesserung geführt

Ich werde jetzt TThread benutzen, da es dort die Synchronize Methode gibt.
Dafür muss natürlich einiges umgebaut werden im Code.
UGrohne
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Do 19.01.06 17:51 
Ohne Code kann ich da natürlich gar nichts dazu sagen. Meine Glaskugel liegt in Deutschland und ich glaube, die hätte mir auch nicht gesagt, was Du in foo machst :roll:

Und richtig angewendet bringt die Critical Section die Abhilfe ...
BattleFrog Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 53

WIN 2000
Delphi 7 Ent.
BeitragVerfasst: Fr 20.01.06 13:22 
Also Gut, ich schaffs net alleine.

Es existiert eine Form mit einem Memo (meDebugLog).
Zur Laufzeit wird ein TServer Objekt erstellt und von draussen senden TCP Clients ihr Anfragen.
Bei jeder Anfrage eines Clients tritt das Ereignis OnExecute des TCP Servers ein, damit man da seinen Code reinhauen kann um zu reagieren und zu verarbeiten.
Soweit kein Probleme.


Hier der Code reduziert auf das wesentliche:

ausblenden volle Höhe 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:
30:
31:
32:
33:
34:
TDebugEvent = procedure (Text: string);

TServer = class
  FTCPServer: TIdTCPServer;
  FOnDebug: TDebugEvent;
private
  procedure HandleOnExecute(AThread: TIdPeerThread);
  procedure Debug(Text: string);
  // weitere Methoden
public
  constructor create;
  property OnDebug: TDebugEvent read FOnDebug write FOnDebug;
end;

constructor TServer.create;
begin
  // TCP Server wird erstellt und aktiviert, usw...

  FTCPServer.OnExecute := HandleOnExecute;
end;

procedure TServer.HandleOnExecute(AThread: TIdPeerThread);
begin
  // hier wird mit privaten TServer Methoden die 
  // Anfrage verarbeitet und ne Antwort gesendet

  Debug('Debugmeldung...');
end;

procedure TServer.Debug(Text: string);
begin
  if assigned(FOnDebug) then
    FOnDebug(Text);
end;


Das OnDebug Ereignis is dazu da, damit die Form die Debugmeldungen in das Memo schreiben kann.
Das klappt auch, solange nicht zu viele Clients gleichzeitig Anfragen senden.
Und meine Vermutung war, das es mit den vielen Threads zu tun hat, die gleichzeitig das Ereignis OnExecute auslösen, in dem wiederum das Ereignis OnDebug ausgelöst wird.

Edit:
OnExecute wird ja selbst aus einem Thread (TIdPeerThread) aufgerufen, ohne eine Critical Section zu benutzen.

Kann man eine Critical Section auch im Hauptthread (Formulare usw) erstellen und so alle anderen "echten" Threads blockieren?
UGrohne
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Veteran
Beiträge: 5502
Erhaltene Danke: 220

Windows 8 , Server 2012
D7 Pro, VS.NET 2012 (C#)
BeitragVerfasst: Fr 20.01.06 20:16 
user profile iconBattleFrog hat folgendes geschrieben:
Kann man eine Critical Section auch im Hauptthread (Formulare usw) erstellen und so alle anderen "echten" Threads blockieren?

Klar kannst Du das. Du kannst also beispielsweise in Deinem Formular, wo das Event verarbeitet wird eine CS einsetzen. Einfach wird es aber wahrscheinlich sein, wenn Du eine CS einfach in Deiner TServer-Klasse implementierst und den Aufruf des Events in Debug in diese CriticalSection setzt. Das sollte IMHO funktionieren.