![]() |
HTTP-Get-Thread NIEMALS zwei gleichzeitig abarbeiten
Hallo,
Das Problem wurde leider immer noch nicht gelöst :( Es wird ein IdHTTPServer betrieben. Im OnGet kommen z.B. Bestellungen rein, die z.B. einen Bondruck mittels FastReport anstoßen. Weil sich der Fastreport aktuell auf einem Form der GUI befindet, darf immer nur ein OnGet einzeln abgearbeitet werden. Also alle OnGet-Ereignisse (insbesondere die Funktion ANTWORTEN_ERZEUGEN) sollen NACHEINANDER abgearbeitet werden. Wenn ein OnGet durch eine Anfrage ausgelöst wird, und gerade schon ein anderer Thread die Funktion ANTWORTEN_ERZEUGEN abarbeitet, dann soll der neue OnGet-Thread VOR ANTWORTEN_ERZEUGEN warten und die Funktion ANTWORTEN_ERZEUGEN erst beginnen, wenn die Funktion in dem anderen Thread VOLLSTÄNDIG abgearbeitet ist. Untenstehend ist der Code zu sehen, mit dem ich das versucht habe. Aber es funktioniert irgendwie nicht. Mein Eindruck ist, dass ein Thread aus der Funktion ANTWORTEN_ERZEUGEN rausspringt bzw fertig ist, obwohl der Druck und/oder die Abarbeitung (z.B. Filtern von Tables und Schleifen durch die Tables) gerade noch stattfindet. Hat jemand zufällig einen Vorschlag, wie man das Problem lösen kann? Mir gehen allmählich die Ideen aus. Falls das eine Rolle spielt: Es wird Firemonkey genutzt. Die Ausgaben "Deadlock detected" und "DoubleGet detected" erscheinen ab und zu beide. Wenn ein Client ab und zu mal ein paar Sekunden warten muss wegen der seriellen Abarbeitung wäre das nicht weiter schlimm. Markus
Code:
procedure TfrmMain.HTTPServerCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); begin try GUI_Lock_Starten_oder_Warten; TThread.Synchronize(nil, procedure begin ANTWORTEN_ERZEUGEN(AContext, ARequestInfo, AResponseInfo); // -> AResponseInfo.ContentText end ); GUI_Lock_Aufheben; except on e:exception do begin AResponseInfo.ContentText := 'Systemfehlermeldung vom Server: ' + e.Message; end; end; end; procedure TfrmMain.GUI_Lock_Starten_oder_Warten; var SperreAktiv : Boolean; warten : integer; begin try SperreAktiv := True; while SperreAktiv do begin try if not HTTP_is_working then begin SperreAktiv := False; end else begin try ButtonDeadlock2.Text := 'DoubleGet detected at ' + DateTimeToStr(Now); except on exception do begin end; end; end; except on e:exception do begin end; end; warten := RandomRange(150,300); Sleep(warten); end; // while HTTP_is_working := True; HTTP_is_working_last_Start := Now; except on e:exception do begin end; end; end; procedure TfrmMain.GUI_Lock_Aufheben; begin try HTTP_is_working := False; except on e:exception do begin end; end; end; procedure TfrmMain.Timer_HTTP_Deadlock_Timeout_prüfenTimer(Sender: TObject); begin try if HTTP_is_working then begin if (Abs(SecondsBetween(HTTP_is_working_last_Start,Now)) > 7) then begin HTTP_is_working := False; // Deadlock übergehen try ButtonDeadlock.Text := 'Deadlock detected at ' + DateTimeToStr(Now); except on e:exception do begin end; end; end; end; except on e:exception do begin end; end; end; |
AW: HTTP-Get-Thread NIEMALS zwei gleichzeitig abarbeiten
Du könntest dir mal TCriticalSection ansehen.
|
AW: HTTP-Get-Thread NIEMALS zwei gleichzeitig abarbeiten
Hmm..
Meines Wissens ist jeder Aufruf von HTTPServerCommandGet bereits ein eigener Thread.. Für das Problem mit Warten, bis anderer Thread fertig empfehle ich mal so: TCriticalSection Eine CriticalSection global in deinem HTTP-Server erzeugen und dann in jedem HTTPServerCommandGet: (Nur so herunter getippt..)
Delphi-Quellcode:
So führt der erste Thread das ANTWORTEN_ERZEUGEN aus und alle anderen warten (durch Acquire) bis er fertig ist.
var
CS : TCriticalSection; // z.B. im initialization erstellt... procedure TfrmMain.HTTPServerCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); begin CS.Acquire; try ANTWORTEN_ERZEUGEN(AContext, ARequestInfo, AResponseInfo); finally CS.Release; end; end; Wenn diese fertig ist (Release), kommt der nächste dran.... Durch die Globale Verwendung ist zu mindestens der gleichzeitige Zugriff aus den Threads auf ANTWORTEN_ERZEUGEN verhindert.. Jedoch dürfte es hier noch Probleme mit HauptThread geben, da wir ja immer noch der (nicht über TCriticalSection) erzeugten und vom Formular verwendeten Report haben. Somit würde ich diesen nicht auf dem Formular platzieren, sondern davon losgelöst in einem eigenen Thread, der auch nur per globaler CriticalSection darauf zugreift... |
AW: HTTP-Get-Thread NIEMALS zwei gleichzeitig abarbeiten
Zitat:
Hat jemand genauere Informationen über den Unterschied zwischen "Enter" und "Acquire"? "Acquire attempts to enter the critical section. It will suspend the calling thread if the critical section is in use by another thread, and will resume as soon as the other thread has released the critical section." "Call Enter to block all other threads from entering code protected by this critical section until the Leave or Release method is called. Enter calls the Acquire method to bind the critical section to the calling thread." Da steht also quasi mit "Acquire" wartet man. Mit "Enter" blockt man und ruft das Warten auf. Was genau macht es dann für einen Sinn, "nur" Acquire aufzurufen? :wall: Markus |
AW: HTTP-Get-Thread NIEMALS zwei gleichzeitig abarbeiten
..vielleicht bringt dieser Thread etwas Erleuchtung:
![]() Grüße Klaus |
AW: HTTP-Get-Thread NIEMALS zwei gleichzeitig abarbeiten
Zitat:
|
AW: HTTP-Get-Thread NIEMALS zwei gleichzeitig abarbeiten
![]() Wenn du die Komponenten auf ein DataModule setzt und pro Thread eine Instanz davon erstellst, könntest du auch unabhängig drucken. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:12 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