Web ページ用の単純なクローラーを開発しています。マルチスレッドクローラーを実装するための多くのソリューションを検索して見つけました。一意の URL を含むスレッドセーフなキューを作成する最良の方法は何ですか?
編集: .Net 4.5 でより良い解決策はありますか?
Web ページ用の単純なクローラーを開発しています。マルチスレッドクローラーを実装するための多くのソリューションを検索して見つけました。一意の URL を含むスレッドセーフなキューを作成する最良の方法は何ですか?
編集: .Net 4.5 でより良い解決策はありますか?
ConcurrentQueueは、実際、フレームワークのスレッドセーフキューの実装です。ただし、プロデューサー/コンシューマーのシナリオで使用する可能性が高いため、実際に必要なクラスは、非常に便利なBlockingCollectionである可能性があります。
Task Parallel Libraryを使用し、ThreadPool を使用するデフォルトのスケジューラを使用します。
OK、これは一度に 30 個の URL をキューに入れる最小限の実装です。
public static void WebCrawl(Func<string> getNextUrlToCrawl, // returns a URL or null if no more URLs
Action<string> crawlUrl, // action to crawl the URL
int pauseInMilli // if all threads engaged, waits for n milliseconds
)
{
const int maxQueueLength = 50;
string currentUrl = null;
int queueLength = 0;
while ((currentUrl = getNextUrlToCrawl()) != null)
{
string temp = currentUrl;
if (queueLength < maxQueueLength)
{
Task.Factory.StartNew(() =>
{
Interlocked.Increment(ref queueLength);
crawlUrl(temp);
}
).ContinueWith((t) =>
{
if(t.IsFaulted)
Console.WriteLine(t.Exception.ToString());
else
Console.WriteLine("Successfully done!");
Interlocked.Decrement(ref queueLength);
}
);
}
else
{
Thread.Sleep(pauseInMilli);
}
}
}
ダミーの使用法:
static void Main(string[] args)
{
Random r = new Random();
int i = 0;
WebCrawl(() => (i = r.Next()) % 100 == 0 ? null : ("Some URL: " + i.ToString()),
(url) => Console.WriteLine(url),
500);
Console.Read();
}
System.Collections.Concurrent.ConcurrentQueue<T>
法案に適合しますか?
System.Collections.Concurrent.ConcurrentQueueを使用します。
複数のスレッドから安全にキューに入れたり、デキューしたりできます。
System.Collections.Concurrent.ConcurrentQueue を見てください。待つ必要がある場合は、System.Collections.Concurrent.BlockingCollection を使用できます。