私はWebサイトのマルチスレッドスクレーパーに取り組んでおり、別の質問に従って、QueueUserWorkItem()でThreadPoolを使用することにしました。
一度にすべてをキューに入れずに、作業項目を継続的にキューに入れるにはどうすればよいですか?300kを超えるアイテム(userIDごとに1つ)をキューに入れる必要があり、それらをすべてキューに入れるためにループすると、メモリが不足します。
だから、私が欲しいのは:
// 1 = startUserID, 300000 = endUserID, 25 = MaxThreads
Scraper webScraper = new Scraper(1, 300000, 25);
webScraper.Start();
// return immediately while webScraper runs in the background
この間、スレッドが使用可能になると、webScraperは300000個のworkItemをすべて継続的に追加します。
これが私がこれまでに持っているものです:
public class Scraper
{
private int MaxUserID { get; set; }
private int MaxThreads { get; set; }
private static int CurrentUserID { get; set; }
private bool Running { get; set; }
private Parser StatsParser = new Parser();
public Scraper()
: this(0, Int32.MaxValue, 25)
{
}
public Scraper(int CurrentUserID, int MaxUserID, int MaxThreads)
{
this.CurrentUserID = CurrentUserID;
this.MaxUserID = MaxUserID;
this.MaxThreads = MaxThreads;
this.Running = false;
ThreadPool.SetMaxThreads(MaxThreads, MaxThreads);
}
public void Start()
{
int availableThreads;
// Need to start a new thread to spawn the new WorkItems so Start() will return right away?
while (Running)
{
// if (!CurrentUserID >= MaxUserID)
// {
// while (availableThreads > 0)
// {
// ThreadPool.QueueUserWorkItem(new WaitCallBack(Process));
// }
// }
// else
// { Running = false; }
}
}
public void Stop()
{
Running = false;
}
public static void process(object state)
{
var userID = Interlocked.Increment(ref CurrentUserID);
... Fetch Stats for userID
}
}
これは正しいアプローチですか?
Start()が呼び出された後、バックグラウンドですべての作業項目を一度に作成するのではなく、作業項目の作成を処理するための正しい方向を誰かに教えてもらえますか?