我正在尝试使用多线程遍历树形结构。问题在于,没有HTTP调用我们就无法知道树的结构(即,HTTP调用将为您提供节点的子项)。因此,我正在尝试使用多线程以增加我们可以进行的HTTP请求的吞吐量。
我不知道我们应该如何优雅地解决这个问题,因此我首先尝试在这里描述我的想法。
最初,我认为这将类似于我们通常编写的BFS,假设我们具有10的并发级别。
我不知道我们应该如何优雅地解决这个问题,因此我首先尝试在这里描述我的想法。
最初,我认为这将类似于我们通常编写的BFS,假设我们具有10的并发级别。
SemaphoreSlim semaphore = new SemaphoreSlim(10);
Task HTTPGet(Node node) {
blah blah
Q.push(childNodes);
}
while (!Q.isEmpty()) {
Node node = Q.head();
Q.pop();
taskList.Add(Task.Start(() => HTTPGet(node));
}
这里的问题是:处理完第一个节点后,Q变为空,整个循环也会终止。因此我认为我们需要检查信号量的剩余计数。如果剩余计数不为10,则表示某些进程仍在运行,我们应该等待其完成。
while (!Q.isEmpty() || semaphore.Count != 10) {
Node node = Q.head();
Q.pop();
taskList.Add(Task.Start(() => HTTPGet(node));
}
但是显然在第一个节点弹出后,Q仍然是空的,我们需要在while循环内部进行一些“等待”,以确保我们可以获取该节点。
while (!Q.isEmpty() || semaphore.Count != 10) {
if (Q.isEmpty()) {
Wait till Q becomes non empty
or semaphore.Count == 10 again
}
Node node = Q.head();
Q.pop();
taskList.Add(Task.Start(() => HTTPGet(node));
}
但是这种方法变得非常丑陋,我相信有更好的解决方法。我试图用生产者-消费者模式来阐述它,但失败了(因为这次消费者也会启动更多的生产者)。
有没有更好的方法来阐述这个问题?