0

ウェブページのソースをメモコンポーネントにダウンロードする最速の方法は何ですか? Indy および HttpCli コンポーネントを使用しています。

問題は、100 を超えるサイトで満たされたリストボックスがあり、プログラムがソースをメモにダウンロードし、そのソースを mp3 ファイル用に解析することです。これは、Google の音楽検索プログラムのようなものです。Google クエリを使用して、Google 検索をより簡単にします。

私は自分の質問につながるスレッドについて読み始めました: 解析機能を持つスレッドで IdHttp インスタンスを作成し、リストボックス内のサイトの半分を解析するように指示できますか?

したがって、基本的にユーザーが解析をクリックすると、メインスレッドは次のことを行う必要があります。

for i := 0 to listbox1.items.count div 2 do
    get and parse

、および他のスレッドは次のことを行う必要があります。

for i := form1.listbox1.items.count div 2 to form1.listbox1.items.count - 1 do
    get and parse.

、したがって、解析されform1.listbox2たコンテンツを同時に追加します。それとも、メイン スレッドで 2 つの IdHttp インスタンスを開始する方が簡単でしょうか。1 つはサイトの前半に、もう 1 つは 2 番目に?

これには、Indy または Synapse を使用する必要がありますか?

4

3 に答える 3

9

単一の URL を読み取ってそのコンテンツを処理できるスレッドを作成します。次に、同時に起動するスレッドの数を決定できます。あなたのコンピュータはかなりの数の接続を許可するので、それらの 100 のサイトが異なるホスト名を持っていても、同時に 10 または 20 を実行しても問題ありません。多すぎるのはやり過ぎですが、少なすぎるのはプロセッサー時間の無駄です。

ダウンロードと処理用に別々のスレッドを用意することで、このプロセスをさらに微調整できます。これにより、多数のスレッドが常にコンテンツをダウンロードできるようになります。ダウンロードはプロセッサにあまり負担をかけません。基本的には応答を待っているため、比較的多数のダウンロード スレッドを簡単に作成できますが、他のいくつかのワーカー スレッドが結果のプールからアイテムを取得して処理することができます。
しかし、ダウンロードと処理を分割すると、もう少し複雑になります。あなたはまだその課題に取り組んでいないと思います.

現在、あなたは他の問題を抱えているからです。最初は、スレッドで VCL コンポーネントを使用することは行われません。スレッド内のリストボックスからの情報が必要な場合は、スレッド内で Synchronize を使用してメイン スレッドへの「安全な」呼び出しを行うか、スレッドを開始する前に必要な情報を渡す必要があります。Synchronize を使用して実行されるコードは実際にはメイン スレッドで実行され、マルチスレッドの効率が低下するため、後者の方が効率的です。

しかし、実際に私の注意を引いたのは、最初の行である「ウェブページのソースをメモ コンポーネントにダウンロードする」です。そうしないでください!これらの結果を処理のためにメモに読み込まないでください。自動処理は、ビジュアル コントロールの外で、メモリ内で行うのが最適です。文字列、ストリーム、さらには文字列リストを使用してテキストを処理すると、メモを使用するよりもはるかに高速になります。
stringlist にも多少のオーバーヘッドがありますが、行のインデックス作成には同じ構造を使用します (Memo の Lines プロパティである TMemoStrings と TStringList は両方とも同じ祖先を持ちます)。これを TStringList に変換するのは非常に簡単です。

于 2011-11-06T19:57:52.370 に答える
5

メインスレッドに解析をまったく行わせないでください。メイン スレッドは UI のみを管理する必要があります。TMemo から HTML を解析しないでください。各スレッドが TStream または String にダウンロードされ、そこから直接解析されます。TIdSync または TIdNotify を使用して、解析結果を UI に送信して表示します (速度が重要な場合は、TIdNotify を使用します)。解析ロジックに UI コンポーネントを含めると、処理が遅くなります。

于 2011-11-06T19:57:33.563 に答える
4

Indy または Synapse はどちらもマルチスレッド対応です。Indy よりもはるかに軽く、目的には十分な Synpase を使用することをお勧めします。Microsoft が提供するHTTP APIを忘れないでください。

簡単な実装:

  • URI ごとに 1 つのスレッド。
  • 各スレッドは、1 つの HTTP 通信を使用してデータを取得します。
  • 次に、各スレッドがデータを解析します。
  • 次に、 を使用Synchronizeして UI を更新します。

おそらく私のお気に入り:

  • 使用する最大スレッド数を定義します (例: 8)。
  • これらの各スレッドはリモート接続を維持します (これが HTTP/1.1 の目的であり、実際に速度に違いをもたらす可能性があります)。
  • すべてのリクエストは、これらのスレッドによって 1 つずつ取得されます。URL をスレッドに事前に割り当てるのではなく、スレッドが 1 つ終了したときにグローバル リストから新しい URL を取得します (各 URL は常に同じ時間を要するわけではありません)。
  • スレッドは、他の URI がグローバル リストに追加されるまで待機する場合があります (Sleep(100)またはセマフォなどを使用)。
  • 次に、専用の GDI メッセージ ( ) を使用して、メイン GUI スレッドで UI を解析および更新しますWM_USER+...- 解析は高速になります (また、UI の更新が遅くなる可能性があることを覚えておいてくださいBeginUpdate-EndUpdate- たとえばメソッドを見てください) - GDI がメッセージ (関連付けられた HTML データを含む) はSynchronize、バックグラウンド スレッドをブロックするものを使用するよりも効率的です。
  • もう 1 つのオプションは、URI からデータを取得した直後に、バックグラウンド スレッドで解析を行うことです。おそらく価値はありません (パーサーが遅い場合のみ)。 100% スレッドセーフではありません。

2 つ目は、いわゆる「ダウンロード マネージャー」がどのように実装されているかです。

マルチスレッドを扱うときは、共有リソース (リストなど) を「保護」する必要があります。aTCriticalSectionを使用して任意のグローバル リスト (URI リストなど) にアクセスし、できるだけ早くロックを解除します。

そして、複数のコンピューターとネットワーク、同時アクセス、さまざまなオペレーティング システムで実装をテストしてみてください。マルチスレッド アプリケーションのデバッグは難しい場合があるため、実装は単純であるほど良いです。これが、ダウンロード部分をマルチスレッドにすることをお勧めする理由ですが、メイン スレッドにデータを処理させます (データはそれほど大きくないので、早くして)。

于 2011-11-07T06:32:30.653 に答える