Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi IdTCPServer - OnExecution und GUI Zugriffe (https://www.delphipraxis.net/124938-idtcpserver-onexecution-und-gui-zugriffe.html)

moelski 27. Nov 2008 14:19


IdTCPServer - OnExecution und GUI Zugriffe
 
Moin !

Ähnlich wie bei den Pipes stosse ich auch beim iDTCPServer auf ein kleines Problem. Und zwar habe ich folgenden Code:
Delphi-Quellcode:
procedure TfrMain.IdTCPServer1Execute(AContext: TIdContext);
var
  request :string;
begin
  request := acontext.Connection.IOHandler.ReadLn;

  Daten := request;

  DecodeCommands;
end;
Daten ist ein globaler String den ich in DecodeCommands auswerte. Dort werden z.B. MDI Childfenster erzeugt.
aber die Anwendung hängt beim Ausführen von DecodeCommands.

Bei meinem Pipe Problem konnte ich das (weil es im Thread läuft) mittels Sychronize lösen. Aber das scheint hier nicht zu klappen. Was muss ich also beim TCPServer tun um mit meiner GUI interagieren zu können beim Execute?

Harry M. 27. Nov 2008 14:44

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
Ebenfalls mit Syncornize des mit dem TCP-Thread des Servers nicht Deines Threads.

Oder mit einer CriticalSection bzw RTL_CriticalSection.

Gruß Harry

PS: und nicht vergessen die CS wieder laufen zu lassen mit CriticalSection.Leave ;)

moelski 27. Nov 2008 14:47

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
Und wie sieht das praktisch aus?

IdTCPServer1.Synchronize gibt es nicht :gruebel:

ChrisE 27. Nov 2008 14:59

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
Hallo,

also ich würde die Daten in einen Buffer schreiben (Array[0..X] of String oder so (genug Plätzte für ca. 2 Sekunden) vielleicht mit TCriticalSection oder so) und dann nicht die Methode direkt aufrufen sonder per Postmessage das Fenster informieren und dort den Index des eben eingetragenen Strings übergeben.

Das sollte gehen.

Gruß, Chris

Edit für Praktisch:
Delphi-Quellcode:
procedure TfrMain.IdTCPServer1Execute(AContext: TIdContext);
var
  request :string;
  naechsterIndex: Integer;
begin
  request := acontext.Connection.IOHandler.ReadLn;
  MyCriticalSection.Enter;
  try
    naesterIndex := (letzterInd +1) mod MAXINDEX_BUFF;
    letzterInd := naesterInd;
    MyDatenArr[naesterIndex] := request;
    PostMessage(Form.Handle, WM_DODECODE_COMMANDS, 0, naesterInd);
  finally
    MyCriticalSection.Leave;
  end;
end;

Harry M. 27. Nov 2008 15:13

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
Delphi-Quellcode:
procedure TForm1.myProc;
begin
  ///..
end;

procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
begin
  AThread.Synchronize(myProc);
end;
oder
Delphi-Quellcode:
uses
SyncObjs;

var
  CS: TCriticalSection;

procedure TForm1.myProc;
begin
  CS.Enter;

  //...

  CS.Leave;
end;

procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
begin
  myProc;
end;

littleDave 27. Nov 2008 15:21

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
Zitat:

Zitat von Harry M.
oder
Delphi-Quellcode:
uses
SyncObjs;

var
  CS: TCriticalSection;

procedure TForm1.myProc;
begin
  CS.Enter;

  //...

  CS.Leave;
end;

procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
begin
  myProc;
end;

Das ist nicht immer korrekt!!! Wenn man jetzt in myProc auf Label1.Caption zugreift, kann es trotzdem krachen. Sagen wir ich habe einen Timer, der jede Millisekunde die Caption von Label1 ausließt. Jetzt kommt myProc daher und ändert Label1.Caption. Jetzt wird der Hauptthread (mit dem Timer) aber von der CriticalSection nicht angehalten, wodurch zwei Methoden gleichzeitig auf ein Objekt zugreifen könnten. Es muss ja nichtmal nen Timer sein, es kann ja auch einfach nur die Paint-Methode sein, falls das Fenster gerade nicht sichtbar war.

Sobald man auf die VCL zugreift, muss man in 99,8% aller Fälle Synchronize() verwenden.

Zudem ist es wirklich nur zu empfehlen, die Critical-Section mit einem try-finally-Block zu versehen:
Delphi-Quellcode:
procedure TForm1.myProc;
begin
  CS.Enter;
  try
    //...
  finally
    CS.Leave;
  end;
end;
Sonst kann es zu Dead-Locks kommen (mehrere Threads warten gleichzeitig auf einen anderen Thread)

moelski 27. Nov 2008 15:39

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
Moin !

Ok, bleibt im Moment noch eine Frage ...

Meine Execution Methode ist so deklariert:
procedure TfrMain.IdTCPServer1Execute(AContext: TIdContext);

Und nicht mit ....IdTCPServer1Execute(AThread: TIdPeerThread); :gruebel:

Harry M. 27. Nov 2008 15:56

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
Unterschiede in der IndyVersion 8 / 9 / 10
Aber von Prinzip das Gleiche

[dekphi]
AContext.Syncronisze
// oder
AContext.Connection.Syncronisze

[/delphi]

moelski 27. Nov 2008 15:59

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
Moin !

Nö das hab ich schon durch.

AContext.Syncronisze
// oder
AContext.Connection.Syncronisze

Hat beides keine Methode Synchronize :cry:

Harry M. 27. Nov 2008 16:06

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
@littleDave

Dann muss die CS natürlich auch in den Timer.

@moelski
Delphi-Quellcode:
AContext.Connection.Socket.Syncronisze
// oder
AContext.Socket.Connection.Syncronisze
Das ist irgendwo versteckt, aber vorhanden.

littleDave 27. Nov 2008 16:12

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
Zitat:

Zitat von Harry M.
@littleDave

Dann muss die CS natürlich auch in den Timer.

Dann hast du zwar den Timer erledigt, aber nicht die Paint-Methode. Es kann ja sein, dass das Fenster genau dann neu gezeichnet werden soll, wenn du gerade die Caption updatest. Wenn du das mit der Critical-Section erledigen möchtest, müsstest du TLabel umschreiben bzw. einen neue Komponente davon ableiten, in der die Paint-Methode von der Critical-Section umgeben ist. Das das natürlich kein sinnvoller Weg ist und nur Probleme machen kann (z.B. bei mehr als einem zusätzlichen Thread, mehreren Critical-Sections, mehreren Labels auf verschiedenen Forms, usw...), sollte man wirklich die Synchronize() - Methode verwenden.

moelski 27. Nov 2008 16:55

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
Moin !

AContext.Connection.Socket.Syncronisze
Nein das geht nicht

AContext.Socket.Connection.Syncronisze
Diese Kombi gibt es so nicht.

Ich finde auch im Web dazu kein Sample :freak:

Hoffe da hat jemand noch den richtigen Tip zur Hand

moelski 27. Nov 2008 21:18

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
Moin !

Also ich habe mein DecodeCommands nun mit CS.Enter CS.Leave versehen. Aber ich bekomme nur eine Exception.

Hoffentlich kann mir noch jemand sagenwo ich das Synchronize web bekomme. Ich habe so langsam alle Möglichkeiten durch, aber es will sich mir nicht zeigen :-(

Apollonius 27. Nov 2008 21:35

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
Zumindest in Delphi 2006 hat TThread auch Klassenmethoden, um mit dem Hauptthread zu synchronisieren.

Klaus01 27. Nov 2008 21:51

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
http://www.indyproject.org/docsite/h...eadMethod.html

http://coding.derkeiler.com/pdf/Arch...9/msg00734.pdf

Dann wie im zweiten Link beschrieben:


Delphi-Quellcode:
if Assigned(AContext.Yarn) and Assigned(TidYarnOfThread(AContext.Yarn).Thread) then
TidYarnOfThread(AContext.Yarn).Thread.Synchronize(MyMethod);
Gute Nacht
Klaus

moelski 28. Nov 2008 07:05

Re: IdTCPServer - OnExecution und GUI Zugriffe
 
Moin !

@Klaus : Danke !

:feuerchen: :cheer:


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:43 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