Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Nur nacheinander abarbeiten bei http get (https://www.delphipraxis.net/200004-nur-nacheinander-abarbeiten-bei-http-get.html)

Markus Effenberger 9. Mär 2019 20:36

Nur nacheinander abarbeiten bei http get
 
Guten Abend Miteinander

Das Projekt nutzt einen idHTTPServer, um Daten bei entsprechender Anfrage an einen Client zu senden.

Um die Fertigstellung des Projektes etwas zu beschleunigen, möchte ich das Ereignis HTTPServerCommandGet so abändern, dass es niemals durch Threads parallel abgearbeitet wird, sondern immer alle Get-Requests nacheinander abgearbeitet werden. Das Problem ist: Es finden GUI-Zugriffe und Tabellen-Zugriffe statt und das crasht natürlich, wenn das parallel passiert. Und das tut es leider, weil ja jeder request in dem idHTTPServer einen eigenen Thread erzeugt.

Ist eine Critical Section bereits eine Lösung? Oder gibt es eine andere Möglichkeit?

Code:
procedure TfrmMain.HTTPServerCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);

  Var Dateiname, Antwort : string;
begin

(...)

//Hier soll bitte gewartet werden, bis kein anderer HTTPServerCommandGet mehr unterhalb dieser Position abgearbeitet wird. Ein paar Sekunden warten ist egal.

(...)

  if ARequestInfo.Params.Values['test'] <> ''
    then begin
      AResponseInfo.ContentText := 'GO' + ARequestInfo.Params.Values['test'];
    end;

  if ARequestInfo.Params.Values['Getliste'] <> ''
    then begin
      AResponseInfo.ContentText := komplette_Tabelle_als_String('liste');
    end;

  if ARequestInfo.Params.Values['GetOberkategorie'] <> ''
    then begin
      AResponseInfo.ContentText := komplette_Tabelle_als_String('Oberkategorie');
    end;

  if ARequestInfo.Params.Values['GetPersonalliste'] <> ''
    then begin
      AResponseInfo.ContentText := komplette_Tabelle_als_String('Personalliste');
    end;

  if ARequestInfo.Params.Values['GetUnterkategorie'] <> ''
    then begin
      AResponseInfo.ContentText := komplette_Tabelle_als_String('Unterkategorie');
    end;

  if ARequestInfo.Params.Values['GetUnternehmensdaten'] <> ''
    then begin
      AResponseInfo.ContentText := komplette_Tabelle_als_String('Unternehmensdaten');
    end;

end;
Ist die Frage verständlich? ;)

DieDolly 9. Mär 2019 20:39

AW: Nur nacheinander abarbeiten bei http get
 
Du könntest die ankommenden Anfragen in irgendeine Liste packen die alle notwendigen Informationen bereit hält und im Hintergrund abgearbeitet wird.

Irgendwie sowas. Aber in jedem Fall mit einer Art Queue, sodass nicht 10 Threads hintereinander erstellt werden, obwohl die vorherigen 5 noch nicht fertig sind.
So, dass immer nur ein Thread zur selben Zeit arbeitet.

DieDolly 9. Mär 2019 20:52

AW: Nur nacheinander abarbeiten bei http get
 
Das kann ich dir nicht sagen. Die Liste muss nicht einmal threadsicher sein denn dort speicherst du lediglich die Informationen, die der Thread nachher bekommen soll der gestartet wird.

Schematisch
[
0,Daten Daten Daten,2019-03-09 21-50,Daten Daten und noch mehr Strings oder so
1,Daten Daten Daten,2019-03-09 22-40,Daten Daten und noch mehr Strings oder so
2,Daten Daten Daten,2019-03-09 23-30,Daten Daten und noch mehr Strings oder so
3,Daten Daten Daten,2019-03-09 24-20,Daten Daten und noch mehr Strings oder so
]

Die wird abgearbeitet und aus den Informationen jeweils ein Thread erstellt der die eigentliche Arbeit macht.
Den Thread den du da irgendwie im Get drin hast würde ich rausnehmen. Oder Daten und GUI trennen. Dann gäbe es auch keine Fehler mehr denke ich.

Markus Effenberger 9. Mär 2019 20:56

AW: Nur nacheinander abarbeiten bei http get
 
Der vorhandene Thread soll einfach nur warten. Wie macht man das?

Die ursprüngliche Frage wurde leider nicht beantwortet.

DieDolly 9. Mär 2019 21:01

AW: Nur nacheinander abarbeiten bei http get
 
Zitat:

Der vorhandene Thread soll einfach nur warten
Einfach gibt es nicht.

Das kann man auch nicht so einfach beantworten schätze ich, ohne auch nur ansatzweise zu wissen wie der Thread aufgebaut ist.
Von Außen sollte man einen Thread eh niemals anhalten. Denn man weiß nie, ob das zu Fehlern führt oder nicht.

Eine einfache Antwort auf deine Frage oder einen einfachen Code, um einen Thread anzuhalten, gibt es nicht.
Wenn man es richtig machen will, ist das mehr Arbeit als nur eine Zeile Code.

Markus Effenberger 9. Mär 2019 21:06

AW: Nur nacheinander abarbeiten bei http get
 
[QUOTE=DieDolly;1427431]
Zitat:

Einfach gibt es nicht.
Vielleicht weiß jemand anderes eine einfache Lösung?

Schokohase 9. Mär 2019 22:51

AW: Nur nacheinander abarbeiten bei http get
 
Die einfachste Art wäre die Verwendung von
Delphi-Quellcode:
System.TMonitor
.
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    IdHTTPServer1: TIdHTTPServer;
    procedure IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo:
        TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
  private
    FLock: TObject;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TForm1.Create(AOwner: TComponent);
begin
  inherited;
  FLock := TObject.Create;
end;

destructor TForm1.Destroy;
begin
  FreeAndNil(FLock);
  inherited;
end;

procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo:
    TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
  System.TMonitor.Enter(FLock);
  try

    // hier jetzt die Abfragen bearbeiten

  finally
    System.TMonitor.Exit(FLock);
  end;
end;
Eine CriticalSection würde auch funktionieren, aber
Delphi-Quellcode:
System.TMonitor
ist da performanter.

Wenn du auf die GUI zugreifen musst (wieso überhaupt) dann musst du natürlich noch mit dem MainThread synchronisieren.

mjustin 10. Mär 2019 08:32

AW: Nur nacheinander abarbeiten bei http get
 
Zitat:

Zitat von Markus Effenberger (Beitrag 1427425)
Es finden GUI-Zugriffe und Tabellen-Zugriffe statt und das crasht natürlich, wenn das parallel passiert. Und das tut es leider, weil ja jeder request in dem idHTTPServer einen eigenen Thread erzeugt.

Ist eine Critical Section bereits eine Lösung? Oder gibt es eine andere Möglichkeit?

TIdHTTPServer ist eine Multithreading-Komponente und startet einen Thread pro HTTP Verbindung. Aus dem Kontext dieses Threads wird OnCommandGet aufgerufen, und aus diesem Thread darf nur synchronisiert auf den Mainthread zugegriffen werden (mit synchronize oder mittels TThread.Queue).

Wenn der Server durch mehrere Anfragen überlastet ist, so sollte er einen passenden HTTP Responsecode zurückliefern und Behandlung des Requests beenden.

Zu blockieren ist nicht sinnvoll, denn wenn mehrere CPU Kerne untätig sind würde so nur einer verwendet.

Schokohase 10. Mär 2019 08:38

AW: Nur nacheinander abarbeiten bei http get
 
Zitat:

Zitat von mjustin (Beitrag 1427439)
Zu blockieren ist nicht sinnvoll, denn wenn mehrere CPU Kerne untätig sind würde so nur einer verwendet.

Natürlich ist es nicht sinnvoll, weil man dadurch Performance vergeudet, aber die Intention des TE ist ja auch nicht die Performance der Anwendung, sondern
Zitat:

Zitat von Markus Effenberger (Beitrag 1427425)
Um die Fertigstellung des Projektes etwas zu beschleunigen, möchte ich das Ereignis HTTPServerCommandGet so abändern, dass es niemals durch Threads parallel abgearbeitet wird, sondern immer alle Get-Requests nacheinander abgearbeitet werden.

Einzig das mit dem GUI Zugriff verstehe ich nicht, wozu der überhaupt benötigt wird.

mjustin 10. Mär 2019 09:20

AW: Nur nacheinander abarbeiten bei http get
 
gelöscht


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:00 Uhr.
Seite 1 von 2  1 2   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz