我正在为一个网站和一个不同的问题,我已经决定使用带有QueueUserWorkItem()的ThreadPool的多线程的刮板。我怎样才能连续QueueUserWorkItems,但一次不排队呢?
我该如何持续排队工作项目而不一次排队呢?我需要排队> 300k项目(每个用户ID一个),如果我循环排队它们,我将耗尽内存。
所以,我想的是:
// 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将所有30万个工作项的线程变得可用。
这是我到目前为止有:
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()时,并且不会一次创建所有工作项目?
在我看来,你需要排列物品的地方。如果您不将它们作为工作项目提供给线程池,则将它们存储在List中,以便稍后可以将其提供给线程池。那是对的吗?如果是这样,将工作存储在线程池中是否真的会将内存释放出来,而将它们存储在自己的列表中却不会将内存释放出来? 如果您确实将它们存储在您自己的列表中,那么您排队等待更多老旧列表的原因很有道理。因此,排队等待线程池中最大线程的2-3倍,并在旧线程完成时排队更多。 – 2009-10-22 03:21:11