[解決済み] 非同期I/Oの同時処理量を制限するには?
質問
// let's say there is a list of 1000+ URLs
string[] urls = { "http://google.com", "http://yahoo.com", ... };
// now let's send HTTP requests to each of these URLs in parallel
urls.AsParallel().ForAll(async (url) => {
var client = new HttpClient();
var html = await client.GetStringAsync(url);
});
ここで問題なのは、1000以上の同時ウェブリクエストを開始することです。これらの非同期 http リクエストの同時実行量を制限する簡単な方法はありますか? 常に 20 以上の Web ページがダウンロードされないようにするためです。最も効率的な方法でそれを行うにはどうすればよいですか?
どのように解決するのですか?
.NET 4.5 Beta を使用して、.NET 用の async の最新バージョンで間違いなくこれを行うことができます。usr」からの前の投稿は、Stephen Toub によって書かれた良い記事を指していますが、あまり発表されていないニュースは、async セマフォが実際に .NET 4.5 のベータ リリースに入ったというものです。
私たちの愛する
SemaphoreSlim
クラスを見てみましょう (これはオリジナルの
Semaphore
を使用する必要があります)、現在では
WaitAsync(...)
シリーズのオーバーロードを誇ります。期待されるすべての引数 - タイムアウト間隔、キャンセルトークン、いつものスケジューリングの仲間たち - があります。)
Stephen はまた、ベータ版で登場した新しい .NET 4.5 の機能についての最近のブログ記事も書いています。 .NET 4.5 Beta の並列処理に関する新機能 .
最後に、SemaphoreSlimを使った非同期メソッドのスロットリングについてのサンプルコードを紹介します。
public async Task MyOuterMethod()
{
// let's say there is a list of 1000+ URLs
var urls = { "http://google.com", "http://yahoo.com", ... };
// now let's send HTTP requests to each of these URLs in parallel
var allTasks = new List<Task>();
var throttler = new SemaphoreSlim(initialCount: 20);
foreach (var url in urls)
{
// do an async wait until we can schedule again
await throttler.WaitAsync();
// using Task.Run(...) to run the lambda in its own parallel
// flow on the threadpool
allTasks.Add(
Task.Run(async () =>
{
try
{
var client = new HttpClient();
var html = await client.GetStringAsync(url);
}
finally
{
throttler.Release();
}
}));
}
// won't get here until all urls have been put into tasks
await Task.WhenAll(allTasks);
// won't get here until all tasks have completed in some way
// (either success or exception)
}
最後になりますが、おそらく言及に値するのは、TPL ベースのスケジューリングを使用するソリューションです。まだ開始されていないデリゲートバインドタスクをTPL上に作成し、カスタムタスクスケジューラで同時実行数を制限できるようにします。実際、そのための MSDN サンプルがここにあります。
また タスクスケジューラ .
関連
-
[解決済み】Excel "外部テーブルが期待された形式ではありません。"
-
[解決済み] 2つのリストを結合する
-
[解決済み】スレッド終了またはアプリケーションの要求により、I/O操作が中断されました。
-
[解決済み] 他のスレッドからGUIを更新するにはどうすればよいですか?
-
[解決済み] async」と「await」の使い方とタイミング
-
[解決済み] 非同期Task<T>メソッドを同期的に実行するにはどうしたらいいですか?
-
[解決済み] C#でawaitを使わずに非同期メソッドを安全に呼び出す方法
-
[解決済み】コンソールアプリのMainメソッドにasync修飾子を指定できない。
-
[解決済み】非同期処理の待ち時間、Wait()でプログラムがフリーズする原因はここにある
-
[解決済み] .Net 4.5の非同期HttpClientは負荷の高いアプリケーションには不向きか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C#で四捨五入する方法
-
[解決済み] [Entity Framework 4.1でエンティティに関連オブジェクトを追加する際に、エンティティオブジェクトをIEntityChangeTracker.の複数のインスタンスから参照できない。
-
[解決済み】プロジェクトビルド時のエラー。エディタでスクリプトにコンパイルエラーがあるため、Playerのビルドにエラーが発生する
-
[解決済み】Visual studio 2019がデバッグ時にフリーズする件
-
[解決済み】「...は'型'であり、与えられたコンテキストでは有効ではありません」を解決するにはどうすればよいですか?(C#)
-
[解決済み】C#のequal to演算子でtextとvarcharのデータ型は互換性がない
-
[解決済み】HttpClientとHttpClientHandlerはリクエストの間にディスポされなければならないのでしょうか?
-
[解決済み】Parallel.ForEachを制限するには?
-
[解決済み】非同期ラムダによる並列foreach
-
[解決済み】Parallel.ForEachでawaitをネストする【重複あり