私はウェブサイトのマルチスレッドスクレーパーに取り組んでいます。異なる質問ごとに、私はQueueUserWorkItem()でThreadPoolを使用することに決めました。どのようにしてQueueUserWorkItemsを連続してキューに入れることなく連続的に行うことができますか?
どのようにして一度にすべての作業項目をキューに入れずにキューに入れることができますか?私は> 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はcontinuousllyすべて300000の作業項目を追加しています。ここで
は、私がこれまで持っているものです。
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()が呼び出され、一度にすべてのワークアイテムを作成しないと、バックグラウンドで作業アイテムの作成を処理するための正しい方法を誰かが指摘できますか?
あなたはどこかのアイテムをキューに入れる必要があるようです。それらをスレッドプールに作業項目として渡していない場合は、それらをリストに格納して、後でスレッドプールに渡すことができます。あれは正しいですか?そうであれば、スレッドプールに作業を格納すると実際にメモリが消えてしまいますが、自分のリストに格納してもメモリが消えませんか? あなた自身のリストにそれらを保存すると、古いものと古いものがキューに入れられることになります。だから、スレッドプールの最大スレッドの2-3倍のようなものをキューイングし、古いものが終了するとキューを追加します。 –