【发布时间】:2014-08-17 11:32:06
【问题描述】:
我正在构建一个刮板。我的目标是启动 X 个浏览器(其中 X 是线程数),然后通过将列表分成 X 个部分来继续抓取每个 URL 的列表。
我决定使用包含 10 个 URL 列表的 3 个线程(3 个浏览器)。
问题:如何像这样在浏览器之间分离每个任务:
Browser1 从 0 到 3 抓取列表中的项目
Browser2 将列表中的项目从 4 刮到 7
Browser3 从 8 到 10 抓取列表中的项目
所有浏览器都应该同时在抓取传递的 URL 列表。
我已经有了这个BlockingCollection:
BlockingCollection<Action> _taskQ = new BlockingCollection<Action>();
public Multithreading(int workerCount)
{
// Create and start a separate Task for each consumer:
for (int i = 0; i < workerCount; i++)
Task.Factory.StartNew(Consume);
}
public void Dispose() { _taskQ.CompleteAdding(); }
public void EnqueueTask(Action action) { _taskQ.Add(action); }
void Consume()
{
// This sequence that we’re enumerating will block when no elements
// are available and will end when CompleteAdding is called.
foreach (Action action in _taskQ.GetConsumingEnumerable())
action(); // Perform task.
}
public int ItemsCount()
{
return _taskQ.Count;
}
可以这样使用:
Multithreading multithread = new Multithreading(3); //3 threads
foreach(string url in urlList){
multithread.EnqueueTask(new Action(() =>
{
startScraping(browser1); //or browser2 or browser3
}));
}
我需要在抓取之前创建浏览器实例,因为我不想在每个线程都启动一个新浏览器。
【问题讨论】:
-
"...因为我不想在每个线程都启动一个新浏览器" - 那么如何并行完成任何工作?
-
@MitchWheat,我的意思是我想从程序一开始就启动X浏览器,一直使用到最后。我通常做的是一个循环,启动浏览器,完成它的工作,关闭浏览器。有没有办法从一开始就启动所有浏览器并使用它们直到结束?
-
为什么线程 1 应该处理 URL 0..3 ?做 0,3,7,... 会有什么问题?
-
@HenkHolterman,对不起,我应该说得更清楚。实际顺序无关紧要,这只是一个例子。我只希望链接在所有浏览器(线程)之间平均分配。
-
为什么要平等?如果一个站点需要更多时间,其他线程是否应该空闲?
标签: c# multithreading