Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi IDHttp und Thread (https://www.delphipraxis.net/111814-idhttp-und-thread.html)

aaron 9. Apr 2008 18:07


IDHttp und Thread
 
Hallo...
Mein Problem ist folgendes:
Ich habe ein Stringgrid in dem in einer Spalte Domainnamen stehen die ich mit IdHttp überprüfen will. Würde das auch gerne mit mittels Threads tun.
Code:
URL := 'http://www.whois.net/whois_new.cgi?d='+Form1.StringGrid1.Cells[1, Form1.StringGrid1.Row];
Klar, die Spalte des Stringgrids müßte erstmal in eine Tstringlist umgewandelt werden.
Nur wie realisiere ich das Abfragen über die Threads?

Habe diese Beispiel gefunden und bin zur Zeit damit am rumprobieren.
Leider funktioniert überhaupt nichts, deshalb hier das gefundene Beispiel:

TBackgroundDownloaderUnit
Code:
unit TBackgroundDownloaderUnit;

interface

uses Classes, Windows,
  IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP;

type
  TReplyReceivedEvent  = procedure (URL, Reply: string) of object;

  TBackgroundDownloader = class (TThread)
                            URL, Reply     : string;
                            OnReplyReceived : TReplyReceivedEvent;
                            IdHTTP         : TIdHTTP;

                            constructor Create (CreateSuspended: boolean);

                            procedure CallUserEvent;
                            procedure Execute; override;
                          end;


implementation

constructor TBackgroundDownloader.Create(CreateSuspended: boolean);
begin
  inherited;
  IdHTTP := TIdHTTP.Create(nil);
end;

procedure TBackgroundDownloader.CallUserEvent;
begin
  if Assigned(OnReplyReceived) then
    OnReplyReceived (URL,Reply);
end;

procedure TBackgroundDownloader.Execute;
begin
  Reply := IdHTTP.Get (URL);

  Synchronize (CallUserEvent);

  IdHTTP.Free;
  IdHTTP := nil;
end;

end.
Ein kleines Demo-Programm zum Testen:

Code:
 
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen } 
  public
    { Public-Deklarationen } 
    procedure IrgendeinName(URL,Reply: string);
  end;

var
  Form1: TForm1;

implementation
uses TBackgroundDownloaderUnit;

{$R *.DFM} 

procedure TForm1.IrgendeinName(URL,Reply: string);
begin
  MessageDlg ('Von der URL'#13#10+URL+#13#10+'kam folgendes zurück:'#13#10#13#10+Reply, mtInformation, [mbOk], 0);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TBackgroundDownloader.Create (true) do
  begin
    URL := 'http://www.quellcodes.de/';
    OnReplyReceived := IrgendeinName;
    Resume;
  end;
end;

end.
Welche Möglichkeiten habe ich?
Grüße
Aaron

Dani 9. Apr 2008 19:26

Re: IDHttp und Thread
 
Zitat:

Nur wie realisiere ich das Abfragen über die Threads?
Leider funktioniert überhaupt nichts
Welche Möglichkeiten habe ich?
Womit genau hast du denn Probleme? Ich versuchs mal etwas allgemeiner...

_______________________________
Eine TThread-Instanz ist ein Objekt, das in der "Execute"-Methode parallel zum Hauptprogramm (welches in einem eigenen Thread läuft) irgendwelche Anweisungen abarbeitet. Wenn nun zwei verschiedene Threads auf ein gemeinsames Datum (z.B. einen String) zugreifen müssen, kann es dazu kommen, dass ein Datum gleichzeitig gelesen und geschrieben wird. Dadurch wird der Wert des Datums unbestimmt und es kommt zu Fehlern.

Um das zu verhindern, müssen Zugriffe auf gemeinsame Daten synchronisiert werden. Man muss irgendwie dafür sorgen, dass das Datum, auf das man zugreift, konsistent ist. Eine einfache Methode dafür sind synchronisierte Ereignisse. Im Wesentlichen werden dabei einfach alle anderen Threads für die Dauer eines Eregnisses angehalten:

Ruft also ein Thread ein Ereignis mit der Methode Delphi-Referenz durchsuchenTThread.Synchronize auf, hat man in diesem Ereignis gesicherten Zugriff, insbesondere auf die Eigenschaften von VCL-Komponenten wie Labels, Edits, etc. Lässt man das synchronize weg, muss man "manuell" mit einer Instanz von Delphi-Referenz durchsuchenTCriticalSection für Konsistenz sorgen.
_______________________________

Also wo hakt es denn? Ist das ganze Konzept mit Klassen, Ereignissen usw. schon klar? Hast du schonmal Luckies Thread-Tutorial durchgelesen?

Edit: du kannst für mehr Lesbarkeit Delphi-Code mit dem [Delphi]-Tag anstelle des [Code] Tags markieren

aaron 9. Apr 2008 22:36

Re: IDHttp und Thread
 
Hallo Dani,
danke für deine ausführliche Erklärungen.

Es hakt bei den Abfragen per IdHttp mit Threads.

Ich habe mich noch nicht viel mit Threads beschäftigt, Klassen und Ereignisse sind für mich keine absoluten Fremdwörter.
Ich sehe mich aber eher als Anfänger, obwohl ich nicht ganz bei Null anfange.
Das Tutorial von Lucky bin ich gerade am lesen.
Ich bin auch nur auf Threads gekommen weil ich in diesem von mir begonnenen "Thread" darauf hingewiesen worden bin, dass das was ich vorhabe nur mit Threads zu lösen ist:
http://www.delphipraxis.net/internal...302&highlight=

Freundliche Grüße
Aaron

[EDIT]Ist das was ich vorhabe sehr kompliziert?

Dani 10. Apr 2008 14:19

Re: IDHttp und Thread
 
Zitat:

Ist das was ich vorhabe sehr kompliziert?
Threads eigenen sich hervorragend, um beliebig komplizierte Fehler zu produzieren :mrgreen:. Ein Problem ist, dass es viele Wege gibt, eine Aufgabe zu lösen. Jede Lösung setzt aber vorraus, dass man weiß, was man tut und was die Rahmenbedingungen sind.

Zitat:

Ich habe ein Stringgrid in dem in einer Spalte Domainnamen stehen die ich mit IdHttp überprüfen will.
Als Programmierer musst du diese Aufgabe in ein Modell umwandeln. Das könnte z.B. so aussehen:

Delphi-Quellcode:
type
  TDomainAbfrageErgebnis = (daUnbekannt, daExistiert, daExistiertNicht);

  TDomainAbfrage = class(TObject)
  private
    FDomain: String;
    FErgebnis: TDomainAbfrageErgebnis;
  public
    constructor Create(Domain: String);
   
    property Domain: String read FDomain write FDomain;
    property Ergebnis: TDomainAbfrageErgebnis read FErgebnis;
  end;
Bitte daran denken, dass dieser Code nicht zum kopieren und einfügen gedacht ist, sondern nur zum Verständnis beitragen soll. Mit dieser Klasse haben wir also schonmal die Ein- und Ausgaben der Aufgabe modelliert. Es fehlt aber noch der Vorgang, wo ermittelt wird, ob die Domain existiert (übrigens würde ich für die reine Namensauflösung lieber IdDNSResolver nehmen). Also:

Delphi-Quellcode:
type
  TDomainAbfrageErgebnis = (daUnbekannt, daExistiert, daExistiertNicht);

  TDomainAbfrage = class(TObject)
  private
    FDomain: String;
    FErgebnis: TDomainAbfrageErgebnis;
  public
    constructor Create(Domain: String);
     
    procedure Durchfuehren;  

    property Domain: String read FDomain write FDomain;
    property Ergebnis: TDomainAbfrageErgebnis read FErgebnis;
  end;

{...}

procedure TDomainAbfrage.Durchfuehren;
var
  DNSResolver: TIdDNSResolver;
begin
  DNSResolver := TIdDNSResolver.Create;
  try
    // Oder wie auch immer TIdDNSResolver funktioniert...das überlasse ich mal dir :)
    // Indy-Exceptions abfangen nicht vergessen!
    case DNSResolver.Resolve(FDomain) of
      Jawohl: FErgebnis := daExistiert;
      Neeein: FErgebnis := daExistiertNicht;
      Fehler: FErgebnis := dsUnbekannt;
    end;
  finally
    DNSResolver.Free;
  end;
end;
Jetzt ist unser Modell in der Lage, das Ergebnis einer DNS-Abfrage zu ermitteln. Aber wo ist der Thread? Irgendwo im Programm muss ja die Methode "Durchfuehren" einer TDomainAbfrage-Instanz aufgerufen werden. Dafür ist der "Arbeiter-Thread" zuständig:

Delphi-Quellcode:
type
  TArbeiterThread = class(TThread)
  private
    FAktuelleAufgabe: TDomainAbfrage;
  protected
    procedure Execute; override;
  end;

implementation

procedure TArbeiterThread.Execute;
begin
  // Pseudocode:
  // "Endlosschleife", welche so lange DNS-Aufgaben abarbeitet, bis keine
  // Aufgaben mehr übrig sind.
  while not Termiated do begin
    Synchronize(HoleNächsteAufgabe);
    if AufgabeWurdeGeholt then begin
      FAktuelleAufgabe.Durchführen;
    end;
  end;
end;
Was man hier nicht sieht: du musst natürlich irgendwo im Programm eine Liste von Threads und eine Liste von Aufgaben verwalten, mit den erwähnten Tücken beim gemeinsamen Zugriff!

So, jetzt hab ich mal einen konkreten Lösungsansatz angerissen. Hast du dazu noch irgendwelche Fragen? Falls nicht, kannst du dir noch alzaimars Workerthread-Pool anschauen. Das ist im Wesentlichen das gleiche Prinzip.

aaron 11. Apr 2008 14:09

Re: IDHttp und Thread
 
HAllo Dani,
vielen...vielen Dank für deine Beispiele.
Ich möchte nicht nur den Domainnamen abfragen sondern noch mehr, also brauche ich den ganzen Quelltext, ich kann dein Beispiel so nicht adaptieren.
Trotzdem nochmal vielen Dank.

Aaron

Dani 11. Apr 2008 14:24

Re: IDHttp und Thread
 
Eigentlich wollte ich dir nie ein funktionierendes Beispiel liefern. Die Hoffnung war, dass du die grundsätzliche Idee aufschnappst und quasi als mündiger, Threads-benutzender Programmierer aus diesem Thema hervorgehst ( :mrgreen: ). Ich kann aber auch eine funktionierende Lösung basteln und hier reinstellen, wenn dir das lieber ist. :|

Dazu müsste ich aber wissen, was genau du meinst mit:
Zitat:

nicht nur den Domainnamen abfragen sondern noch mehr
Was muss denn alles "abgefragt" werden? Willst du nur einen einfachen GET oder POST-Request senden oder willst du dich auf ner Website einloggen und dann irgendwelche Dinge tun?

aaron 11. Apr 2008 14:55

Re: IDHttp und Thread
 
Zitat:

Zitat von Dani
Eigentlich wollte ich dir nie ein funktionierendes Beispiel liefern. Die Hoffnung war, dass du die grundsätzliche Idee aufschnappst und quasi als mündiger, Threads-benutzender Programmierer aus diesem Thema hervorgehst ( :mrgreen: ). Ich kann aber auch eine funktionierende Lösung basteln und hier reinstellen, wenn dir das lieber ist. :|

Ich will das schon selber können... aber es wäre wirklich richtig hammasuper wenn du mir ein konkretes Beispiel geben könntest.

Zitat:

Zitat von Dani
Was muss denn alles "abgefragt" werden? Willst du nur einen einfachen GET oder POST-Request senden oder willst du dich auf ner Website einloggen und dann irgendwelche Dinge tun?

Ich habe immer
Delphi-Quellcode:
IdHttp1.get('http://www.whois.net/whois_new.cgi?d='+Form1.StringGrid1.Cells[1, Form1.StringGrid1.Row];
verwendet.
Ich durchsuche dann immer den Quelltext nach einem bestimmten Wort, wenn dieses Wort gefunden wird dann soll in das Stringgrid ein "Ja" geschrieben werden andernfalls ein "Nein".
Nochmal Danke!
Freundliche Grüße
Aaron

Dani 11. Apr 2008 20:03

Re: IDHttp und Thread
 
Liste der Anhänge anzeigen (Anzahl: 1)
Nach dem Wort suchen musst du selbst (in TWhoisLookupJob.Execute) :P

aaron 12. Apr 2008 02:15

Re: IDHttp und Thread
 
Hallo Dani
Wahnsinn, das hätte ich so schnell nicht hinbekommen auch nicht in den nächsten Monaten.
Danke.
Freundliche Grüße
Aaron

aaron 12. Apr 2008 19:27

Re: IDHttp und Thread
 
Hallo Dani,

zwei "kleine" Fragen habe ich doch noch. :shock:
Wo ich die Threadgeschwindigkeit steuern, ist das überhaupt möglich?

Wäre das dazu die richtige Stelle für ein IDHttp.Timeout?
Delphi-Quellcode:
  try
    HTTP.HandleRedirects := true;
    try
      FReply := HTTP.Get(Format(WHOIS_LOOKUP_FORMATSTR, [FURL]));
      FSuccess := true;
      HTTP.ConnectTimeout:=1500;
    except
Viele Grüße
Aaron


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