2016-05-09 18 views
1

我需要幫助來加速我的項目,我有2個ListBox,第一個是滿了URL,第二個我在其中存儲導致404錯誤的URL,它只是檢查處理。在idhttp大約需要2秒來檢查1個網址,我不需要的HTML,導致解密過程需要一定的時間,所以我決定在我的項目中添加線程,到目前爲止我的代碼如何在delphi 10中使用帶idhttp的線程

unit Unit1; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
    System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, 
    IdSSLOpenSSL, Vcl.StdCtrls, IdBaseComponent, IdComponent, 
    IdTCPConnection, IdTCPClient, IdHTTP; 

type 
    TForm1 = class(TForm) 
    IdHTTP1: TIdHTTP; 
    Button1: TButton; 
    ListBox1: TListBox; 
    ListBox2: TListBox; 
    Button3: TButton; 
    Memo1: TMemo; 
    procedure Button1Click(Sender: TObject); 
    procedure Button2Click(Sender: TObject); 
    procedure Button3Click(Sender: TObject); 

private 

public 

end; 

Type 
    TMyThread = class(TThread) 
    IdHTTP1: TIdHTTP; 
    Button1: TButton; 
    ListBox1: TListBox; 
    ListBox2: TListBox; 
    Button3: TButton; 
    Memo1: TMemo; 

    private 
    fStatusText : string; 
    lHTTP: TIdHTTP; 

    protected 
    procedure Execute; override; 
    public 
    Constructor Create(CreateSuspended : boolean); 
    end; 

var 
    Form1: TForm1; 

procedure TForm1.Button3Click(Sender: TObject); 
var 
    MyThread : TMyThread; 
begin 
    MyThread := TMyThread.Create(True); 
    MyThread.Start; 
end; 

constructor TMyThread.Create(CreateSuspended : boolean); 
var 
    s: string; 
    IdSSL : TIdSSLIOHandlerSocketOpenSSL; 
begin 
    FreeOnTerminate := True; 
    inherited Create(CreateSuspended); 
    lHTTP := TIdHTTP.Create(nil); 
    IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil); 
    try 
    lHTTP.ReadTimeout := 30000; 
    lHTTP.IOHandler := IdSSL; 
    IdSSL.SSLOptions.Method := sslvTLSv1; 
    IdSSL.SSLOptions.Method := sslvTLSv1; 
    IdSSL.SSLOptions.Mode := sslmUnassigned; 
    lHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(lHTTP); 
    lHTTP.HandleRedirects := True; 
    finally 

    end; 
end; 

destructor TMyThread.Destroy; 
begin 
    inherited; 
end; 

procedure TMyThread.Execute; 
var 
    s: string; 
    i: Integer; 
    satir: Integer; 
    str: TStringList; 
    newStatus : string; 
begin 
    fStatusText := 'TMyThread Starting...'; 
    Synchronize(Showstatus); 
    fStatusText := 'TMyThread Running...'; 
    while (not Terminated) do 
    begin 
    for i:= 0 to satir-1 do 
    begin 
     try 
     lHTTP.Get('http://website.com/'+ListBox1.Items.Strings[i]); 
     Memo1.Lines.Add(ListBox1.Items[i]) 
     except 
     on E: EIdHTTPProtocolException do 
     begin 
      if E.ErrorCode <> 404 then 
      raise; 
      ListBox2.Items.Add(ListBox1.Items[i]); 
     end; 
     end; 
    end; 
    end; 
    if NewStatus <> fStatusText then 
    begin 
    fStatusText := newStatus; 
    Synchronize(Showstatus); 
    end; 
end; 

procedure TMyThread.ShowStatus; 
begin 
    Form1.Caption := fStatusText; 
end; 

end. 

現在,當我打BUTTON3的表格標題去TMyThread is Starting...,沒有什麼事情發生!!請看看代碼,非常感謝。

+0

你的代碼是一個爛攤子。首先,修復格式。然後添加其餘部分(聲明'TMyThread = class(TThread)'的部分。 –

+0

好的,完成@KenWhite – ColdZer0

+0

*請*瞭解如何正確格式化代碼(在此處和代碼編輯器中)。使得它更容易閱讀和理解 –

回答

3

對於每個URL,您應該使用單獨的線程,而不是使用循環遍歷所有URL的單個線程 。

嘗試一些更喜歡這個:

unit Unit1; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
    System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, 
    Vcl.StdCtrls; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    ListBox1: TListBox; 
    ListBox2: TListBox; 
    Button3: TButton; 
    Memo1: TMemo; 
    procedure Button1Click(Sender: TObject); 
    procedure Button2Click(Sender: TObject); 
    procedure Button3Click(Sender: TObject); 
    private 
    procedure MyThreadPathResult(const APath: string; AResult: Boolean); 
    procedure MyThreadStatus(const AStr: string); 
    end; 

var 
    Form1: TForm1; 

implementation 

uses 
    IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, IdSSLOpenSSL; 

type 
    TMyThreadPathResultEvent = procedure(const APath: string; AResult: Boolean) of object; 
    TMyThreadStatusEvent = procedure(const APath, AStr: string) of object; 

    TMyThread = class(TThread) 
    private 
    fPath: string; 
    fOnPathResult: TMyThreadPathResultEvent; 
    fOnStatus: TMyThreadStatusEvent; 
    procedure PathResult(AResult: Boolean); 
    procedure ShowStatus(const Str: string); 
    protected 
    procedure Execute; override; 
    public 
    constructor Create(const APath: string); reintroduce; 
    property OnPathResult: TMyThreadPathResultEvent read fOnPathResult write fOnPathResult; 
    property OnStatus: TMyThreadStatusEvent read fOnStatus write fOnStatus; 
    end; 

procedure TForm1.Button3Click(Sender: TObject); 
var 
    i: Integer; 
    Thread: TMyThread; 
begin 
    for i := 0 to ListBox1.Items.Count-1 do 
    begin 
    Thread := TMyThread.Create(ListBox1.Items.Strings[i]); 
    Thread.OnPathResult := MyThreadPathResult; 
    Thread.OnStatus := MyThreadStatus; 
    Thread.Start; 
    end; 
end; 

procedure TForm1.MyThreadPathResult(const APath: string; AResult: Boolean); 
begin 
    if AResult then 
    Memo1.Lines.Add(APath) 
    else 
    ListBox2.Items.Add(APath); 
end; 

procedure TForm1.MyThreadStatus(const AStr: string); 
begin 
    Caption := AStr; 
end; 

constructor TMyThread.Create(const APath: string); 
begin 
    inherited Create(True); 
    FreeOnTerminate := True; 
    fPath := APath; 
end; 

procedure TMyThread.Execute; 
var 
    lHTTP: TIdHTTP; 
    IdSSL: TIdSSLIOHandlerSocketOpenSSL; 
begin 
    ShowStatus('TMyThread Starting...'); 

    lHTTP := TIdHTTP.Create(nil); 
    try 
    lHTTP.ReadTimeout := 30000; 
    lHTTP.HandleRedirects := True; 

    IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(lHTTP); 
    IdSSL.SSLOptions.Method := sslvTLSv1; 
    IdSSL.SSLOptions.Mode := sslmClient; 
    lHTTP.IOHandler := IdSSL; 

    ShowStatus('TMyThread Running...'); 

    try 
     lHTTP.Get('http://website.com/'+fPath, TStream(nil)); 
    except 
     on E: EIdHTTPProtocolException do 
     begin 
     if E.ErrorCode = 404 then 
      PathResult(False) 
     else 
      raise; 
     end; 
    end; 
    finally 
    lHttp.Free; 
    end; 

    PathResult(True); 
end; 

procedure TMyThread.PathResult(AResult: Boolean); 
begin 
    if Assigned(fOnPathResult) then 
    begin 
    TThread.Synchronize(
     procedure 
     begin 
     if Assigned(fOnPathResult) then 
      fOnPathResult(fPath, AResult); 
     end 
    ); 
    end; 
end; 

procedure TMyThread.ShowStatus(const Str: string); 
begin 
    if Assigned(fOnStatus) then 
    begin 
    TThread.Synchronize(
     procedure 
     begin 
     if Assigned(fOnStatus) then 
      fOnStatus(fPath, Str); 
     end 
    ); 
    end; 
end; 

end. 

雖這麼說,你可以考慮使用Delphi的Parallel Programming Library代替:

unit Unit1; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
    System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, 
    Vcl.StdCtrls; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    ListBox1: TListBox; 
    ListBox2: TListBox; 
    Button3: TButton; 
    Memo1: TMemo; 
    procedure Button1Click(Sender: TObject); 
    procedure Button2Click(Sender: TObject); 
    procedure Button3Click(Sender: TObject); 
    end; 

var 
    Form1: TForm1; 

implementation 

uses 
    System.Threading, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, IdSSLOpenSSL; 

procedure TForm1.Button3Click(Sender: TObject); 
begin 
    TParallel.&For(0, ListBox1.Items.Count-1, 
    procedure(AIndex: Integer) 
    var 
     lPath: string; 
     lHTTP: TIdHTTP; 
     IdSSL: TIdSSLIOHandlerSocketOpenSSL; 
    begin 
     TThread.Synchronize(nil, 
     procedure 
     begin 
      Form1.Caption := 'Task Starting...'; 
      lPath := ListBox1.Items.Strings[AIndex]; 
     end; 
     end; 

     lHTTP := TIdHTTP.Create(nil); 
     try 
     lHTTP.ReadTimeout := 30000; 
     lHTTP.HandleRedirects := True; 

     IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(lHTTP); 
     IdSSL.SSLOptions.Method := sslvTLSv1; 
     IdSSL.SSLOptions.Mode := sslmClient; 
     lHTTP.IOHandler := IdSSL; 

     TThread.Synchronize(nil, 
      procedure 
      begin 
      Form1.Caption := 'Task Running...'; 
      end; 
     end; 

     try 
      lHTTP.Get('http://website.com/'+lPath, TStream(nil)); 
     except 
      on E: EIdHTTPProtocolException do 
      begin 
      if E.ErrorCode = 404 then 
      begin 
       TThread.Synchronize(nil, 
       procedure 
       begin 
        Form1.ListBox2.Items.Add(lPath); 
       end 
      ); 
      end; 
      Exit; 
      end; 
     end; 
     finally 
     lHttp.Free; 
     end; 

     TThread.Synchronize(nil, 
     procedure 
     begin 
      Form1.Memo1.Lines.Add(lPath); 
     end 
    ); 
    end 
); 
end; 

end. 

或者:

unit Unit1; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
    System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, 
    Vcl.StdCtrls; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    ListBox1: TListBox; 
    ListBox2: TListBox; 
    Button3: TButton; 
    Memo1: TMemo; 
    procedure Button1Click(Sender: TObject); 
    procedure Button2Click(Sender: TObject); 
    procedure Button3Click(Sender: TObject); 
    end; 

var 
    Form1: TForm1; 

implementation 

uses 
    System.Threading, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, IdSSLOpenSSL; 

procedure TForm1.Button3Click(Sender: TObject); 
var 
    i: Integer; 
    lPath: string; 
begin 
    for i := 0 to ListBox1.Items.Count-1 do 
    begin 
    lPath := ListBox1.Items.Strings[i]; 
    TTask.Create(
     procedure 
     var 
     lHTTP: TIdHTTP; 
     IdSSL: TIdSSLIOHandlerSocketOpenSSL; 
     begin 
     TThread.Synchronize(nil, 
      procedure 
      begin 
      Form1.Caption := 'Task Starting...'; 
      end; 
     end; 

     lHTTP := TIdHTTP.Create(nil); 
     try 
      lHTTP.ReadTimeout := 30000; 
      lHTTP.HandleRedirects := True; 

      IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(lHTTP); 
      IdSSL.SSLOptions.Method := sslvTLSv1; 
      IdSSL.SSLOptions.Mode := sslmClient; 
      lHTTP.IOHandler := IdSSL; 

      TThread.Synchronize(nil, 
      procedure 
      begin 
       Form1.Caption := 'Task Running...'; 
      end; 
      end; 

      try 
      lHTTP.Get('http://website.com/'+lPath, TStream(nil)); 
      except 
      on E: EIdHTTPProtocolException do 
      begin 
       if E.ErrorCode = 404 then 
       begin 
       TThread.Synchronize(nil, 
        procedure 
        begin 
        Form1.ListBox2.Items.Add(lPath); 
        end 
       ); 
       end; 
       Exit; 
      end; 
      end; 
     finally 
      lHttp.Free; 
     end; 

     TThread.Synchronize(nil, 
      procedure 
      begin 
      Form1.Memo1.Lines.Add(lPath); 
      end 
     ); 
     end 
    ).Start; 
    end; 
end; 

end.