5

Web テスト ツールの URL リストに基づいて HTML ページ ソースを取得する必要がある .NET 4 ヘルパー/ユーティリティ クラスを実装しようとしています。ソリューションはスケーラブルで高性能でなければなりません。

私はすでに何日もの間、さまざまな解決策を調査して試してきましたが、適切な解決策を見つけることができません。

私の理解に基づいて、私の目標を達成するための最良の方法は、TPL を使用して並行して実行される非同期 Web リクエストを使用することです。

ヘッダーなどを完全に制御するために、HttpWebResponse をラップしている WebClient の代わりに HttpWebResponse を使用しています。場合によっては、出力を他のタスクにチェーンする必要があるため、TPL タスクを使用することは理にかなっています。

さまざまな試行錯誤を経てこれまでに達成したことは、

  1. 基本的な同期、非同期 (APM) および並列 (TPL タスクを使用) ソリューションを実装して、さまざまなソリューションのパフォーマンス レベルを確認しました。

  2. 非同期並列ソリューションのパフォーマンスを確認するために、APM アプローチの BeginGetResponse と BeginRead を使用し、Parallel.ForEach で実行しました。すべてがうまく機能し、パフォーマンスに満足しています。どういうわけか、単純な Parallel.ForEach を使用するのは適切ではないと感じています。たとえば、タスクチェーンをどのように使用すればよいかわかりません。

  3. 次に、TaskCompletionSource と iterator を使用して APM フローを反復することにより、APM ソリューションをラップするためのタスクを使用する、より高度なシステムを試しました。この解決策は私が探しているものである可能性があると信じていますが、500 の URL リストを実行すると 6 ~ 10 秒の奇妙な遅延が 2 ~ 3 回発生します。

    ログに基づいて、実行は、遅延が発生したときにループで非同期フェッチを呼び出しているスレッドに戻りました。遅延は、実行がループに戻ったときに常に発生するとは限りません.2〜3回だけで、それ以外の場合は正常に動作します. ループ スレッドは、他のスレッドによって処理される一連のタスクを作成し、ほとんど/すべてのタスクが完了する間、ループが残りのタスクを作成し続け、他のスレッドが再びアクティブになるまでに遅延 (6-8 秒) があるようです。 .

ループ内の反復子の原則は次のとおりです。

IEnumerable<Task> DoExample(string input) 
    { 
    var aResult = DoAAsync(input); 
    yield return aResult; 
    var bResult = DoBAsync(aResult.Result); 
    yield return bResult; 
    var cResult = DoCAsync(bResult.Result); 
    yield return cResult; 
    … 
    }

Task t = Iterate(DoExample(“42”));

System.Net.ServicePointManager.DefaultConnectionLimit を使用して接続制限を解決し、ThreadPool.RegisterWaitForSingleObject を使用してタイムアウトを解決しています

私の質問は、次のような html ページを取得するためのヘルパー/ユーティリティ クラスを実装するための最良の方法は何でしょうか。

  • スケーラブルで高性能
  • ウェブリクエストを使用する
  • 他のタスクに簡単に連鎖する
  • タイムアウトを使用できる
  • .NET 4 フレームワークを使用する

上記で紹介した APM、TaskCompletionSource、および iterator を使用したソリューションで問題ないと思われる場合は、遅延の問題を解決するための助けをいただければ幸いです。

私は C# と Windows の開発にまったく慣れていないので、私が試していることがあまり意味をなさない場合でも気にしないでください。

これを解決しないとテストツールの開発をやめなければならないので、どんな助けも大歓迎です。

ありがとう

4

1 に答える 1

0

イテレータの使用は、TPL以前の.NETの優れたソリューションでした(たとえば、MSRoboticsのCoordinationand Concurrency Runtime(CCR)は、イテレータを多用し、TPLを刺激するのに役立ちました)。1つの問題は、イテレーターだけでは必要なものが得られないことです。ワークロードを効果的に分散するには、スケジューラーも必要です。これは、リンク先のStephen Toubのスニペットによってほぼ完了していますが、次の1行に注意してください。

enumerator.Current.ContinueWith(recursiveBody, TaskContinuationOptions.ExecuteSynchronously);

あなたが見ている断続的な問題は、「ExecuteSynchronously」を強制することに関連している可能性があると思います-それは利用可能なコア/スレッド間で作業の不均一な分散を引き起こしている可能性があります。

スティーブンが彼のブログ記事で提案している他のいくつかの選択肢を見てください。特に、ContinueWith()呼び出しの単純なチェーンを実行するだけで何が行われるかを確認してください(必要に応じて、Unwrap()呼び出しを照合します)。構文は最もきれいではありませんが、最も単純で、基礎となるワークスティーリングランタイムへの干渉ができるだけ少ないため、より良い結果が得られることを願っています。

于 2012-06-06T06:09:00.897 に答える