1

私のアプリケーションは、テキスト コンテンツを取得して、URL のリストを処理する必要があります。私のインターネット接続は

myTimeOut:= 2000;
InternetSetOption(nil, INTERNET_OPTION_CONNECT_TIMEOUT, Pointer(@myTimeOut), SizeOf(myTimeOut));
InternetSetOption(nil, INTERNET_OPTION_SEND_TIMEOUT, Pointer(@myTimeOut), SizeOf(myTimeOut));
InternetSetOption(nil, INTERNET_OPTION_RECEIVE_TIMEOUT, Pointer(@myTimeOut), SizeOf(myTimeOut));

URLの読み取りごとに個別のスレッドを起動しています

(...)
read_url_threads[thread_counter]:= TReadURLThread.Create(false);
read_url_threads[thread_counter].FreeOnTerminate:= False;
read_url_threads[thread_counter].myURL:= target_url_list[i];
read_url_threads[thread_counter].output_filename:= local_output_filename;
read_url_threads[thread_counter].NetHandle:= NetHandle;
read_url_threads[thread_counter].limit_text_size:= max_length_url;
hArr[thread_counter]:= read_url_threads[thread_counter].Handle;
(...)
if (thread_counter >= max_threads) or
   (thread_counter >= (target_url_list.Count)) then

   repeat
     rWait:= WaitForMultipleObjects(thread_counter, @hArr,True, 100);
     Application.ProcessMessages;
   until rWait <> WAIT_TIMEOUT;
(...)

スレッド実行内で、次の方法で URL コンテンツを取得します。

   if Assigned(NetHandle) and (not EndsText('.pdf',url)) then
    try
      UrlHandle := InternetOpenUrl(NetHandle, PChar(url), nil, 0, 0, 0);
      if Assigned(UrlHandle) then
        try
          repeat
            InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);
            SetString(StrBuffer, PAnsiChar(@Buffer[0]), BytesRead);
            Result := Result + StrBuffer;
          until BytesRead = 0;
        finally
          InternetCloseHandle(UrlHandle);
        end;

私の問題は、InternetReadFile ルーチンのタイムアウトを設定することです。一部の URL では、数分間スタックすることがあります。このサイクルでタイムアウトを強制する最良の方法は何ですか?

4

1 に答える 1

3

構成されたタイムアウトが効果がない場合 (これは既知のバグです)、接続ハンドルを閉じる必要があります。これにより、関連する関数が強制的に失敗し、プログラムに制御が戻ります。Microsoft の記事Q224318の「2 番目のスレッドを作成して接続タイムアウト値を制御する方法」では、その方法について説明しています。InternetReadFile(別のスレッドが戻るのを待ってスタックしているため、別のスレッドが必要です。)

于 2012-07-20T20:41:05.177 に答える