2

私は過去 2 日間、この問題の真相を断続的に突き止めようとしてきましたが、本当に行き詰っています。うまくいけば、賢い人々が私を助けてくれるでしょう。

問題は、渡された Web サイトから (Synapse ライブラリを使用して) ファイルをダウンロードするスレッドで呼び出す関数があることです。ただし、ファイルをプルダウンしないサイトがときどきあることがわかりましたが、wget または Firefox/IE では問題なくダウンロードされます。

調べてみると、気になるものを見つけました。関連するコードは次のとおりです。

uses
//[..]
  HTTPSend,
  blcksock;

//[..]

type
  TMyThread = class(TThread)
  protected
    procedure Execute; override;
  private
    { Private declarations }
    fTheUrl: string;
    procedure GetFile(const TheUrl: string);
  public
    property thrd_TheUrl: string read fTheUrl write fTheUrl;
  end;

implementation

[..]

procedure TMyThread.GetFile(const TheUrl: string);
var
  HTTP: THTTPSend;
  success: boolean;
  sLocalUrl: string;
  IsSame : boolean;
begin

  HTTP := THTTPSend.Create;
  try
    HTTP.UserAgent :=
      'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)';
    HTTP.ProxyHost := 'MYPROXY.COM';
    HTTP.ProxyPort := '80';

    sLocalUrl :=
      'http://web.archive.org/web/20071212205017/energizer.com/usbcharger/download/UsbCharger_setup_V1_1_1.exe';


   IsSame :=  SameText(sLocalUrl, sTheUrl); //this equals True when I debug

   ///
   ///
   /// THIS IS WHERE THE ISSUE BEGINS
   ///  I will comment out 1 of the following when debugging
   ///
    HTTP.HTTPMethod('GET', sLocalUrl); // ----this works and WILL download the file
    HTTP.HTTPMethod('GET', sTheUrl);  // --- this always fails, and HTTP.ResultString contains "Not Found"

    success := SysUtils.UpperCase(HTTP.ResultString) = 'OK';


    if HTTP.ResultCode > 0 then
      success := True; //this is here just to keep the value around while debugging
  finally
    HTTP.Free;
  end;
end;

procedure TMyThread.Execute
begin
   //fTheURL contains this value:  http://web.archive.org/web/20071212205017/energizer.com/usbcharger/download/UsbCharger_setup_V1_1_1.exe

   GetFile(fTheUrl);
end;

問題は、関数にローカル変数を割り当てて URL を直接指定すると、すべてが機能することです。ただし、変数を関数に渡すと失敗します。誰にもアイデアはありますか?

    HTTP.HTTPMethod('GET', sLocalUrl); // ----this works and WILL download the file
    HTTP.HTTPMethod('GET', sTheUrl);  // --- this always fails, and HTTP.ResultString contains "Not Found"

SVN リポジトリの Synapseの最新バージョン(2 日前のバージョン) を使用しています。

注: ダウンロードしようとしているファイルはウイルスに感染していることがわかっています。私が作成しているプログラムは、分析のために悪意のあるファイルをダウンロードすることを目的としています。そのため、ダウンロードしたファイルを実行しないでください。

ただし、この URL b/c を使用しています。これは、問題を再現できる URL です。

4

3 に答える 3

4

TMyThreadコードには、クラスの使用方法に関する重要な詳細が欠けています。しかし、あなたは書く

時々、ファイルをプルダウンしないサイトがありますが、wget または Firefox/IE では問題なくダウンロードされます。

これはタイミングの問題のように聞こえます。

ローカル変数の使用は毎回機能します。function パラメーターを使用しても機能しない場合があります。これは、関数パラメータに正しい URL が含まれていないことが原因である場合があります

中断されていないスレッドを作成すると、構築呼び出しの後の次の行が実行を開始する前に、すぐに実行が開始される可能性があることに注意する必要があります。したがって、スレッドの作成後にスレッド オブジェクトのプロパティを設定しても、スレッドの実行がプロパティの読み取りポイントを過ぎている可能性があるため、機能しない場合があります。スレッド オブジェクトのfTheUrlフィールドは、最初は空の文字列になるため、スレッドがファイルをダウンロードするかどうかは、以前に設定されているかどうかによって異なります。

あなたのfTheUrlフィールドは、同期プリミティブによってさえ保護されていません。スレッド proc とメイン スレッドのコードの両方が同時にアクセスできます。このようにスレッド間でデータを共有することは安全ではなく、誤った動作から実際のクラッシュまで、あらゆる事態を引き起こす可能性があります。

スレッドが実際に 1 つのファイルをダウンロードするために使用されている場合は、プロパティへの書き込みアクセスを削除し、URL のパラメーターを使用してカスタム コンストラクターを記述する必要があります。これにより、スレッドが開始する前にフィールドが適切に初期化されます。

プログラムで複数のファイルをダウンロードする場合は、それぞれに対してスレッドを作成するべきではありません。ダウンロードするファイルが割り当てられるスレッドのプール (1 つだけの場合もあります) を使用します。そのためには、スレッド プロパティが適切なソリューションですが、同期を使用して実装する必要があります。また、ファイルをダウンロードしない場合はスレッドをブロックし、プロパティが設定されている場合はブロックを解除する必要があります。ダウンロード スレッド (または複数のスレッド) は、プロデューサー/コンシューマー実装のコンシューマーです。スタック オーバーフローでは、Delphi タグに、これに関する質問と回答がありSuspend()ますResume()

Execute()最後に 1 つ: 未処理の例外がメソッドから逃げないようにしてください。Delphi 2010 がこれらの例外を VCL で処理するかどうかはわかりませんが、スレッドで未処理の例外が発生すると、アプリのクラッシュやフリーズなどの問題が発生する可能性があります。

于 2010-03-12T05:24:11.517 に答える
0

報告するのが恥ずかしいのですが、時間を割いて回答してくださった方々のおかげです。

この問題は、Synapse や TThread とは関係ありませんが、URL で大文字と小文字が区別されるという事実にすべて関係していました

完全なアプリケーションでは、(何らかの理由で) URL を小文字にするヘルパー関数がありました。それを削除すると、すべてが再び機能し始めました...

于 2010-03-13T06:47:33.330 に答える
0

最後の Synapse リビジョン 127 に更新してください。

于 2010-04-30T19:04:22.630 に答える