Also ich hab mit Indy9 das Problem bisher noch nicht gehabt. Bei dir sind mir aber ein paar Sachen aufgefallen, die nicht so dolle sind:
- AThread.Start und AThread.Terminate sind komplett unnötig, da der Thread schon gestartet ist.
- Das Event wird von dem Thread ausgelöst und arbeitet ohne Synchronize(); . Somit sind
VCL-Aufrufe innerhalb des Threads ohne Synchronize verboten. Genauso ist es mit Application.ProcessMessages;. Du musst das nicht ausführen, da sowieso alles in einem Thread ausgeführt wird und die Hauptanwendung somit nicht beeinträchtigt wird (kannst ja mal in dem Event zum Spaß ein Sleep(1000000); einbauen und du wirst sehen, dass die Anwendung währenddessen ganz normal weiterläuft).
Ich glaube dein Problem ist, dass du aus dem Thread-Event heraus auf die
VCL zugreifst (z.B.
melog.lines.Add) und dein Programm somit früher oder später sich selbst zerschießt. Außerdem: warum speicherst du die Parameter erst in einem Memo, dass du dann später wieder auswertet?
Delphi-Quellcode:
meparams.Lines := ARequestInfo.Params;
meparams.Lines.add('');
meparams.Lines.add(inttostr(AThread.ThreadID));
Wenn jetzt mehrere Request auf einmal kommen, kann der Inhalt von meparams totaler Schwachsinn werden, da du NICHT Synchronisierst!
In diesem Event musst du komplett Thread-Save arbeiten: kein Zugriff auf die
VCL ohne Synchronize, Critical-Sections für andere Sachen usw. Jedoch ist es in dem Event nicht sinnvoll, es zu synchronisieren. Wenn du das machst, ist der große Vorteil - nähmlich dass jede Verbindung ihren eigenen Thread hat - aufeinmal weg. Am besten wäre es, wenn du in diesem Event auf keine
VCL-Sachen zugreifst (Buttons usw.). StringListen sind kein Problem - solange sie nur in einem Thread verwendet werden (ist bei dir mit sl, sl1, sl2 ja so). Aber auf Memos in der Hauptform solltest du nicht zugreifen, da dadurch 1. nur unnötiger Aufwand wegen Synchronisierung entsteht und 2. weil dann der Thread-Vorteil dahin ist.
Ich schreib mal das Event für dich etwas um:
Delphi-Quellcode:
uses
SyncObjs;
var
logCritical : TCriticalSection;
logMessage :
string;
procedure TForm1.SyncLogMessage;
begin
melog.Lines.Add(logMessage);
end;
procedure TForm1.DoLogMessage(AThread: TIdPeerThread; msg:
string);
begin
// diese Critical-Section ist dafür da, dass nicht mehrere Threads gleichzeitig
// die globale Variable "logMessage" bearbeiten können
logCritical.Enter;
try
logMessage := msg;
AThread.Synchronize(SyncLogMessage);
finally
logCritical.Leave;
end;
end;
procedure TForm1.IdHTTPServer1CommandGet(AThread: TIdPeerThread;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
sl, sl1, sl2 : TStringlist;
StartTime, EndTime : TDateTime;
lGWDataService : IGWDataService;
i : integer;
Ergebnis :
string;
begin
StartTime := Now;
// Objekte erzeugen
sl := TStringList.Create;
sl1 := TStringList.Create;
sl2 := TSTringList.Create;
try
for i:=0
to ARequestInfo.Params.Count -1
do
begin
if Pos('
VO=', ARequestInfo.Params.Strings[i]) > 0
then
SplitString(ARequestInfo.Params.Strings[i], '
=', sl);
if Pos('
NA=', ARequestInfo.Params.Strings[i]) > 0
then
SplitString(ARequestInfo.Params.Strings[i], '
=', sl1);
end;
// Abfrage in einer DB auf Vorname und nachname
AResponseInfo.ResponseNo := 200;
// HTTP-STATUS-OK
AResponseInfo.ResponseText := sl2[1];
AResponseInfo.WriteHeader;
AResponseInfo.WriteContent;
EndTime := Now;
DoLogMessage(AThread, '
Aufruf des Service zu Verarbeitung : ' +
Formatdatetime('
ss.zzz', EndTime - StartTime) +
'
mit der Session ID = ' + IntToStr(AThread.ThreadID));
finally
// Objekte wieder freigeben
sl.Free;
sl1.Free;
sl2.Free;
end;
end;
initialization
LogCritical := TCriticalSection.Create;
finalization
LogCritical.Free;
(nicht geprüft, da Delphi nicht offen)