私は、並列処理とノンブロッキングの同時実行が利用可能です。
サーバーは、Windows 2008 および .NET 4.0 を実行するクアッド コア (vCPU) VPS です (新しい async/await は使用できません)。
何を指示してるんですか?
更新:これまでに提案されたオプションは、Reactive Extensions (Rx)、Async CTP、TPL です。
Async CTP が理想的な方法で、Rx と TPL がそれに続くようです。みんな何て言う?
私は、並列処理とノンブロッキングの同時実行が利用可能です。
サーバーは、Windows 2008 および .NET 4.0 を実行するクアッド コア (vCPU) VPS です (新しい async/await は使用できません)。
何を指示してるんですか?
更新:これまでに提案されたオプションは、Reactive Extensions (Rx)、Async CTP、TPL です。
Async CTP が理想的な方法で、Rx と TPL がそれに続くようです。みんな何て言う?
最終的に使用する非同期アプローチに関係なく、デフォルトはドメインごとに 2 であるため、許可される最大接続数を増やす必要があることを忘れないでください。そのため、1 つのドメインに対して多くの呼び出しを行うと、その速度に制限されます。
基本構成を使用して、スタンドアロン (非 ASP.NET) アプリでこれを修正できます。
<system.net>
<connectionManagement>
<add address="*" maxconnections="200" />
</connectionManagement>
</system.net>
ただし、ASP.NET を使用している場合、これは期待どおりに機能しません。これは、デフォルトの<processModel autoConfig="true" ...>
属性によりコアあたり 12 に自動構成されるため、合計 2 よりも優れていますが、それでもニーズに合わない可能性があるためです。そのため、Application_Start などでコードベースのアプローチを使用する必要があります。
ServicePointManager.DefaultConnectionLimit = 200;
注: このコード ベースのアプローチは、ASP.NET 以外のアプリでも同様に機能するため、.config を避けたい場合は、"ユニバーサル" ソリューションとして使用できます。
そのタスクにはRxを使用します。
string[] webpages = { "http://www.google.com", "http://www.spiegel.de"};
webpages
.Select(w => FetchWebPage(w))
.ForkJoin()
.Subscribe(x => /*This runs when all webpages have been fetched*/ Console.WriteLine(x));
または、svickが提案したように、同時実行を制御して最大4つの要求を同時に処理する場合は、次のように変更できます。
Observable.ForkJoin(
webpages
.Select(w => FetchWebPage(w))
.Merge(4))
.Subscribe(x => /*This runs when all webpages have been fetched*/ Console.WriteLine(x));
また、通常の非同期方式からRx方式に変換するためのヘルパーメソッドも必要です。
public static IObservable<string> FetchWebPage(string address)
{
var client = new WebClient();
return Observable.Create<string>(observer =>
{
DownloadStringCompletedEventHandler handler = (sender, args) =>
{
if (args.Cancelled)
observer.OnCompleted();
else if(args.Error != null)
observer.OnError(args.Error);
else
{
observer.OnNext(args.Result);
observer.OnCompleted();
}
};
client.DownloadStringCompleted += handler;
try
{
client.DownloadStringAsync(new Uri(address));
}
catch (Exception ex)
{
observer.OnError(ex);
}
return () => client.DownloadStringCompleted -= handler;
});
}
VS2010 SP1 は、Async CTP を使用して .NET 4.0を実行できasync
ます。await
VS2012 RC は、Async Targeting Pack を使用して .NET 4.0を実行できasync
ます。await
async
ただし、本当に/を使用したくない場合await
でも、タスクと継続を使用できます (Task Parallel Library は .NET 4.0 の一部です)。
私にも同様のニーズがありましたが、私の場合、URL の数は 7,000 を超えています (完了までに約 25 ~ 28 分かかりました)。私のソリューションでは、TPL を使用しました。各 URL には依存関係がないため、それぞれをオブジェクトにカプセル化し、コレクションに配置して、そのコレクションを Parallel.ForEach() 呼び出しに渡すだけで簡単にできました。
ダウンロードが完了するたびに、ページのコンテンツを確認し、見つかった内容に応じて、追加の処理のために送信します。
私が言ったように、これは完了するのに 30 分の大半を要していましたが、現在は約 4.5 分で実行されます (私はデュアル クアッド コア Xeon プロセッサ @ 3GHz、Windows 7 Ultimate 64 ビット エディション、および 24 GB の RAM を使用しています)。 .... ほとんどが浪費されているのに対して、現在利用されている十分な電力)。
私は Microsoft の TPL に非常に感銘を受けたので、レガシー プロジェクト/コードのほとんどに戻り、可能な場合は TPL を利用するように設計をリファクタリングしました。ループの反復間に何らかのタイプの依存関係がある場合は、常に可能であるとは限りません)。
私は最近、HttpWebRequest の代わりに C# 5 の新しい非同期機能と WebClent を使用して、同様のことを行いました。DownloadDataTaskAsync などの WebClient を使用すると、いくつかの優れた非同期メソッドを取得できます。
WebClient client = new WebClient();
byte[] data = await client.DownloadDataTaskAsync(url)