Einzelnen Beitrag anzeigen

Benutzerbild von littleDave
littleDave

Registriert seit: 27. Apr 2006
Ort: München
556 Beiträge
 
Delphi 7 Professional
 
#2

Re: idhttpserver mehere Anfragen gleichzeitig verarbeiten

  Alt 5. Aug 2008, 13:17
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)
Jabber: littleDave@jabber.org
in case of 1 is 0 do external raise while in public class of object array else repeat until 1 is 0
  Mit Zitat antworten Zitat