Entwickler-Ecke
Internet / Netzwerk - url aufrufen und abbruch nach 3 sekunden oder bei 404
idefix123456 - Mi 13.04.11 19:09
Titel: url aufrufen und abbruch nach 3 sekunden oder bei 404
Hallo,
Nach stundenlangem Suchen und ausprobieren, frage ich hier einfach mal nach. Ich habe die untere Funktion. Damit rufe ich eine URL im Hintergrund auf. Als Result wird mir dann der JSON übergabe wert als String zurückgeliefert. Ziel ist es von Delphi aus Daten über die URL an das php script auf meinen Server zu schicken, dieser wertet das ganze aus, und schickt einen json string an Delphi zurück. Soweit funktioniert das Ganze auch super! Vorausgesetzt es besteht eine Internet Verbindung!
Und da liegt mein Problem. Wenn keine Verbindung besteht, dann Versucht die funktion quasi in einer Endlosschleife die URL zwanghaft doch zu öffnen, was ja nicht geht, und deswegen hängt sich immer die komplette Form auf wodurch ich das Programm beenden muss!
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| function LoadURL(url: string): string; var HttpLoader: TIdHttp; begin HttpLoader := TIdHttp.Create; try result := HttpLoader.Get(url); finally HttpLoader.Free; end; end; |
Jetzt versuche ich seit Stunden einen Timeout mit in der funktion einzubauen. Also das die funktion 3 sekunden lang versuchen kann die URL zu öffnen, wenn das nicht gelingt wird die funktion abgebrochen, und false zurückgeliefert!
Habe schon:
Idhttp1.ReadTimeout := 3000;
Idhttp1.ConnectTimeout := 3000;
ausprobiert, das funktioniert aber nicht, da dennoch nicht abgebrochen wird.
Wer kann helfen?
Danke
jaenicke - Mi 13.04.11 19:54
Da Indy mit blocking sockets arbeitet, wird das nicht so gehen. Das ist aber ohnehin wenig sinnvoll so, da du deinen Hauptthread so blockierst.
Lagere das ganze am besten in einen Thread aus. Dafür erzeuge dir zuerst mit CreateEvent ein Ereignis. Dieses gibst du dann zusammen mit der Adresse an den Thread weiter. Danach wartest du mit MsgWaitForMultipleObjects (mit QS_ALLINPUT) auf dein Ereignis (ohne Timeout, damit nichts blockiert) und wartest bis du entweder ein Ergebnis bekommst oder die 3 Sekunden herum sind. In der Schleife kannst du Application.ProcessMessages aufrufen.
Im Thread wiederum hast du diesen Quelltext. Wenn du die Seite erfolgreich abrufen konntest, speicherst du das Ergebnis in einer public Eigenschaft des Threads und löst dann mit SetEvent das Ereignis aus.
Außerhalb des Threads bekommst du jetzt von MsgWaitForMultipleObjects gemeldet, dass das Ereignis ausgelöst wurde und du kannst das Ergebnis aus der Eigenschaft des Threads lesen.
Auf diese Weise kannst du ohne deine GUI zu blockieren warten. Du kannst natürlich auch gar nicht warten und auf das Signal aus dem Thread warten, dass er fertig ist, aber das würde die Bestimmung des Timeouts schwieriger machen, es sei denn der Thread verschluckt das Ergebnis einfach nach dem Ende des Timeouts. Ganz wie du möchtest. ;-)
idefix123456 - Do 14.04.11 15:09
Hi,
Danke für die Antworten...
Da ich noch nicht so richtig mit Threads gearbeitet habe, hab ich mich mal ein wenig bei google drüber schlau gemacht und folgenden code zusammengeschustert (ungetestet)
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46:
| var GlobalURL: string;
procedure OpenURLResult(json: string); begin
ShowMessage(json);
end;
procedure OpenURLThread();
function LoadURL(url: string): string; var HttpLoader: TIdHttp; begin HttpLoader := TIdHttp.Create; try result := HttpLoader.Get(url); finally HttpLoader.Free; end; end; var json: string; begin
json := LoadURL(GlobalURL); OpenURLResult(json);
end;
procedure OpenURL(url: string); var ThreadID: DWORD; begin GlobalURL := url; CreateThread(nil, 0, TFNThreadStartRoutine(@OpenURLThread), nil, 0, ThreadID); end; |
Wenn ich jetzt OpenURL('http://www.google.de') ausführe, sollte eingentlich ein einem neuen Thread das ganze gestartet werden, und wenn eine Verbindung hergestellt ist, sollte die procedure OpenURLResult ausgeführt werden.
Jetzt habe ich noch 2 fragen, und zwar wenn das ganze nun in einem Nebenthread anstatt in dem Haupttread gestartet wird und es besteht Keine Verbindung zum Internet, dann müsste sich aber doch der Nebenthread dennoch aufhängen anstatt wie zuvor die Komplette Form (da ja trotzdem kein Abbruch nach 3 skeunden). Das sich der Thread Aufhängt sollte doch eigentlich egal sein, aber Verbraucht das dann nicht doch dennoch Resourcen???
Außerdem könntest du das mit dem MsgWaitForMultipleObjects und das "speicherst du das Ergebnis in einer public Eigenschaft des Threads und löst dann mit SetEvent das Ereignis aus" nochmal etwas genauer erklären!
Danke
haentschman - Do 14.04.11 21:45
Hallo...
da du noch nie mit Threads gearbeitet hast empfehle ich dir TThread. Dieses ist etwas leichter zu verstehen als der direkte Weg über die API. Suche mal hier im Forum danach.
jaenicke - Fr 15.04.11 06:16
idefix123456 hat folgendes geschrieben : |
| Außerdem könntest du das mit dem MsgWaitForMultipleObjects und das "speicherst du das Ergebnis in einer public Eigenschaft des Threads und löst dann mit SetEvent das Ereignis aus" nochmal etwas genauer erklären! |
Ganz kurz als Gerüst, weil ich bald zur Arbeit los muss:
Im Hauptthread:
Delphi-Quelltext
1: 2: 3:
| MyEvent := CreateEvent(nil, True, False, nil); MyThread := TUrlLoadThread.Create(MyUrl, MyEvent); Wait... |
Im Thread:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| property LoadResult: string read FLoadResult;
constructor Create(const AUrl: string; AMyEvent: THandle); begin FMyUrl := AMyUrl; FMyEvent := AMyEvent; inherited Create(False); end;
procedure Execute; begin ... FLoadResult := ... SetEvent(FMyEvent); end; |
Für die Wait-Funktion schau dir am besten das an:
http://www.delphipraxis.net/6620-delay.html
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!