Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   IdHTTP Get im Thread sofort unterbrechen? (https://www.delphipraxis.net/194751-idhttp-get-im-thread-sofort-unterbrechen.html)

LTE5 1. Jan 2018 14:31

IdHTTP Get im Thread sofort unterbrechen?
 
Mit dieser Unit erspare ich mir doppelten Code und erzeuge eine TIdHTTP-Instanz
Delphi-Quellcode:
unit HTTPObject;

interface

uses
 System.Classes, IdHTTP, IdSSLOpenSSL;

type
 THTTPObject = class(TIdHTTP)

 private
  IOHndl: TIdSSLIOHandlerSocketOpenSSL;
 public
  constructor Create(AOwner: TComponent);
  destructor Destroy; override;
 end;

implementation

constructor THTTPObject.Create(AOwner: TComponent);
begin
 inherited;

 IOHndl := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
 Request.BasicAuthentication := True;
 HandleRedirects := False;
 IOHandler := IOHndl;
 ReadTimeout := 10000;
end;

destructor THTTPObject.Destroy;
begin
 IOHndl.Free;

 inherited;
end;

end.
Delphi-Quellcode:
aHTTP := THTTPObject.Create(nil);
try
 X := aHTTP.Get( --- );
finally
 aHTTP.Free;
end;
Obiger Aufruf ist in einem Thread.

Wie kann ich nun bei Programmbeendigung dieses Get() sofort unterbrechen?
Den Thread terminieren funktioniert leider nicht wegen dem Get() was noch am arbeiten ist.

Der schöne Günther 1. Jan 2018 14:41

AW: IdHTTP Get im Thread sofort unterbrechen?
 
http://www.delphipraxis.net/173890-w...gewaltsam.html

Tl;dr: Klar kannst du ihn, z.B. mit WinApi-Routinen hart abschießen. Aber man sollte das nicht tun. Wenn jemand in meinem Büro ist und ich meine Ruhe haben möchte bitte ich ihn auch freundlich den Raum zu verlassen und schieße ihm nicht einfach in den Kopf.

LTE5 1. Jan 2018 14:41

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Es geht mir nicht um den Thread sondern um das IdHTTP.Get.

Der schöne Günther 1. Jan 2018 14:49

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Die Suchmaschine meines Vertrauens meint man könne das
Delphi-Quellcode:
OnWork
-Event verwenden um dort dann abzubrechen, z.B. mittels
Delphi-Quellcode:
Disconnect()
oder Werfen einer Exception.

Aber das hast du sicher schon gesehen - Wird das Event nicht aufgerufen bei deinem hohen
Delphi-Quellcode:
ReadTimeout
wenn er einfach nur hängt?

LTE5 1. Jan 2018 14:52

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Zitat:

Aber das hast du sicher schon gesehen - Wird das Event nicht aufgerufen bei deinem hohen ReadTimeout wenn er einfach nur hängt?
Noch nicht. Ich gucke gleich mal nach was passiert wenn ich Disconnect aufrufe.

Wie hoch sollte so ein Timeout denn gewöhnlich sein?

himitsu 1. Jan 2018 15:01

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Einen Thread kann/darf man niemals von außen "beenden". Man muß immer dem Thread, bzw. dem Code darin, sagen, dass er sich beenden soll.
Die potentiellen Folgen wären sonst Deadlocks, Speicherlecks oder Schlimmeres.

Also TThread.Terminate und TThread.Terminated im Thread.
Und natürlich den "länger" wartenden Funktionen im Thread. (ebenfalls auf Terminated reagieren oder z.B. Terminate überschreiben und das da durchreichen)

Im genannten OnWork könntest du dann diese Anfrage prüfen, oder du suchst in TIdHTTP oder besser im TIdHTTP.IOHandler, ob es da einen Cancel-Befehl gibt.

LTE5 1. Jan 2018 15:03

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Einen Cancelbefehl gibt es nicht.
Das hier führt auch nicht zum Erfolg. Es dauert immer circa 19 Sekunden bis das Programm beendet wird.

Delphi-Quellcode:
type
 THTTPObject = class(TIdHTTP)

 private
  FCanceled: Boolean;
  IOHndl: TIdSSLIOHandlerSocketOpenSSL;
  procedure FOnWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
 public
  constructor Create(AOwner: TComponent);
  destructor Destroy; override;

 published
  property Canceled: Boolean read FCanceled write FCanceled;
 end;

implementation

constructor THTTPObject.Create(AOwner: TComponent);
begin
 inherited;

 FCanceled := False;
 IOHndl := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
 Request.BasicAuthentication := True;
 HandleRedirects := False;
 IOHandler := IOHndl;
 ReadTimeout := 10000;

 OnWork := FOnWork;
end;

procedure THTTPObject.FOnWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
 if FCanceled then
  begin
   raise Exception.Create('Disconnect');

   Disconnect;
  end;
end;
Delphi-Quellcode:
aHTTP.Canceled := True;
_Thread.Terminate; // Wird respektiert: "einen Thread kann/darf man niemals von außen "beenden". Man muß immer dem Thread, bzw. dem Code darin, sagen, dass er sich beenden soll."

HolgerX 1. Jan 2018 16:15

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Hmm..

Zitat:

Zitat von LTE5 (Beitrag 1390029)
Delphi-Quellcode:
procedure THTTPObject.FOnWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
 if FCanceled then
  begin
   raise Exception.Create('Disconnect');

   Disconnect;
  end;
end;

Dir ist bewusst, dass das 'Disconnect' nach dem 'raise Exception..' nie zur Ausführung kommt? ;)

Versuche mal ein Tausch.

(Ungetestet, nur so gelesen...)

LTE5 1. Jan 2018 16:22

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Zitat:

Dir ist bewusst, dass das 'Disconnect' nach dem 'raise Exception..' nie zur Ausführung kommt?
Habe schon sämtliche Kombinationen durch. Selbst wenn das Disconnect ausgeführt wird muss ich diese 20 Sekunden warten.

Genau hier beim Head muss ich warten. Vollkommen egal welche URL ich eingebe. Bei Get muss ich ebenfalls warten.

Ich habe glaube ich vergessen zu erwähnen, dass ich nur warten muss wenn keine Internetverbindung besteht.
Delphi-Quellcode:

// Unit 1
aHTTP := THTTPObject.Create(nil);
try
 if UrlCheck(aHTTP, ---) = 200 then
  .....

// Unit 2
function UrlCheck(aHTTP: THTTPObject = nil; sUrl: string = ''): Integer;
begin
 Result := -1;

 try
  if sUrl <> '' then
   begin
    aHTTP.Head(sUrl);
    Result := aHTTP.Response.ResponseCode;
   end;
 except
  Result := GetLastError;
 end;
end;

hoika 1. Jan 2018 21:52

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Hallo,
das ist der TimeOut von Windows.
Kannst Du den nicht in der Komponente zusetzen?

LTE5 1. Jan 2018 21:57

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Zitat:

das ist der TimeOut von Windows.
Gut zu wissen.
Zitat:

Kannst Du den nicht in der Komponente zusetzen?
Man kann zwei verschiedene Timeouts setzen aber beide interessieren Windows nicht.

Delphi.Narium 2. Jan 2018 00:09

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Wenn Windows wartet, dann wartet Windows. Erst wenn das mit der Warterei fertig ist, kannst Du im Programm reagieren, nur dass das dann sowieso schon reagiert.

Solange von Windows nix kommt, wird onWork nicht aufgerufen, da ja nicht "geworkt" wird. Von daher hilft es nichts, wenn man da Disconnect aufruft und/oder 'ne Exception wirft. OnWork eignet sich für Fortschrittsanzeigen ..., also alles, was man bei funktionierender Arbeit machen kann. Das ist beim TimeOut aber nicht gegeben.

Mir ist momentan kein Weg bekannt, wie man da "mal eben" rauskommt.

Eventuell dasda? http://smallbusiness.chron.com/chang...ons-45899.html

Eventuell mal mit windows internet timeout bei der Suchmaschine Deiner Wahl stöbern gehen.

In 'nem threadlosen Programm hab' ich das etwas unelegant gelöst:

Es gibt da 'nen Timer, im OnWorkBegin wird er eingeschaltet und im OnWorkEnd wieder ausgeschaltet. Der hat ein Interval von 15 Sekunden. Wenn er "zuschlägt" wird im Timerereignis sowas gemacht:
Delphi-Quellcode:
idhttp.Disconnect(True);
idhttp.IOHandler.InputBuffer.Clear;
Wenn Du den Timer und sein Ereignis mit in den Thread nehmen kannst, könnte das ja eventuell ein Lösungsansatz sein. Ob der gut ist, entscheiden bitte andere, mit Threads hab' ich es nicht so ;-)

Ein Ansatz zur Umsetzung ist aber eventuell garnicht so weit: Thread + Timer, Einbinden von TimerThread.pas bzw. im Ursprung: http://www.delphipraxis.net/1270100-post13.html

LTE5 2. Jan 2018 00:36

AW: IdHTTP Get im Thread sofort unterbrechen?
 
So ganz verstehe ich nicht was es mit " http://www.delphipraxis.net/181814-t...hread-pas.html " aufsich hat.

Für mich ist das nur ein TThread mit Events zum Warten statt mit einem Sleep(1234).

himitsu 2. Jan 2018 00:37

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Wenn/da Indy bestimmt ReadFile und WriteFile für das Auslesen/Senden des TCP-Datenstroms verwendet, kann man sowas z.B. über
MSDN-Library durchsuchenCancelIo, MSDN-Library durchsuchenCancelIoEx oder MSDN-Library durchsuchenCancelSynchronousIo aus jedem Thread unterbrechen.

Aber hier wartet es ja schon beim Öffnen der Verbindung (ala CreateFile oder so) und da gibt es keinen Abbruchbefehl, aber hier sollte man irgendwo auch den passenden Timeout einstellen können (denk ich mir).

Towmuz 2. Jan 2018 07:36

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Zitat:

Zitat von LTE5 (Beitrag 1390035)
Ich habe glaube ich vergessen zu erwähnen, dass ich nur warten muss wenn keine Internetverbindung besteht.

Dann prüf doch erstmal ob eine Internetverbindung besteht bevor du was mit GET machst.

Der schöne Günther 2. Jan 2018 09:22

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Vielleicht bin ich nicht so schlau, aber wie soll man das konkret prüfen? Was er macht ist doch völlig legitim. Oder muss er vor dem Prüfen "ob eine Internetverbindung besteht" dann noch prüfen ob überhaupt eine Netzwerkkarte im PC steckt? Und davor prüfen ob ...

Delphi.Narium 2. Jan 2018 09:49

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Da Indy benutzt wird, ist auch der TIdIcmpClient vorhanden. Damit kann man ein Ping absetzen. Beim Programmstart oder an geeigneter Stelle:
Delphi-Quellcode:
IdIcmpClient.Host := 'www.delphipraxis.net'; // Oder der Host, bei dem per Get Daten geholt werden sollen.
Try
  IdIcmpClient.Ping;
Except
  on e : Exception do begin
    MessageDlg(e.Message,mtError,mbOk,0);
    // Oder dafür sorgen, dass der Thread irgendwie erfährt:
    // Die Internetverbindung funktioniert nicht so recht.
  end;
end;
// und die Ereignisroutine zum IdIcmpClient:
procedure TForm1.IdIcmpClientReply(ASender: TComponent; const AReplyStatus: TReplyStatus);
begin
  // Hier den Thread starten ...
end;

TiGü 2. Jan 2018 09:54

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1390075)
Vielleicht bin ich nicht so schlau, aber wie soll man das konkret prüfen? Was er macht ist doch völlig legitim. Oder muss er vor dem Prüfen "ob eine Internetverbindung besteht" dann noch prüfen ob überhaupt eine Netzwerkkarte im PC steckt? Und davor prüfen ob ...

Auf Windows-Systemen größer Vista würde sich der INetworkListManager anbieten:
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

Die Pascal-Unit erhält man über Delphi IDE -> Component -> Import Component -> Import a Type Library -> Network List Manager 1.0 Type Library

Dieser hat zwei praktische Getter/Properties, um Netwerk- und Internet-Konnektivität zu prüfen.

Towmuz 2. Jan 2018 09:59

AW: IdHTTP Get im Thread sofort unterbrechen?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1390075)
Vielleicht bin ich nicht so schlau, aber wie soll man das konkret prüfen? Was er macht ist doch völlig legitim. Oder muss er vor dem Prüfen "ob eine Internetverbindung besteht" dann noch prüfen ob überhaupt eine Netzwerkkarte im PC steckt? Und davor prüfen ob ...

Ich dacht ihn stört der Timeout, wenn das eine globale Windowseinstellung ist, dann ists doch eher unschön daran rumzuschrauben oder nicht?

Könnte man ja vorher Pingen (aber da gibt´s ja auch einen Timeout :p)

Ansonsten dürfte das hier wohl keine große Verzögerung ergeben InternetGetConnectedState, bzw. INetworkListManager::GetConnectivity.


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