我正在为网站开发多线程抓取工具,根据另一个问题,我决定将 ThreadPool 与 QueueUserWorkItem() 一起使用。
我怎样才能不断地排队工作项而不是一次将它们全部排队?我需要排队 > 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 在线程可用时不断添加所有 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() 后在后台处理创建工作项的正确方向,而不是一次创建所有工作项吗?