asp.net 递归函数MultiThreading一次执行一个任务

s3fp2yjn  于 2023-10-21  发布在  .NET
关注(0)|答案(4)|浏览(140)

我正在写一个程序来抓取网站。抓取功能是一个递归的,可能会消耗更多的时间来完成,所以我使用多线程来执行多个网站的抓取。我到底需要的是,完成后爬行一个网站,它调用下一个(这应该是在Queqe),而不是多个网站在同一时间爬行。我使用C#和ASP.NET。

9o685dep

9o685dep1#

这样做的标准做法是使用blocking queue。如果你使用的是.NET 4.0,那么你可以利用BlockingCollection类,否则你可以使用Stephen Toub的实现。
您要做的是,根据需要启动尽可能多的工作线程,并让它们在无限循环中循环,在队列中出现项目时对它们进行删除。你的主线将围绕该项目。阻塞队列被设计为等待/阻塞出队操作,直到项目变得可用。

public class Program
{
  private static BlockingQueue<string> m_Queue = new BlockingQueue<string>();

  public static void Main()
  {
    var thread1 = new Thread(Process);
    var thread2 = new Thread(Process);
    thread1.Start();
    thread2.Start();
    while (true)
    {
      string url = GetNextUrl();
      m_Queue.Enqueue(url);
    }
  }

  public static void Process()
  {
    while (true)
    {
      string url = m_Queue.Dequeue();
      // Do whatever with the url here.
    }
  }
}
t2a7ltrp

t2a7ltrp2#

当涉及到网络爬虫时,我通常不会有积极的想法.

你想用threadpool

ThreadPool.QueueUserWorkItem(new WaitCallback(CrawlSite), (object)s);

您只需将工作负载“推入”队列,并让线程池管理它。

zengzsys

zengzsys3#

我不得不说-我不是一个线程Maven,我的C#是相当生 rust -但考虑到需求,我会建议这样的东西:
1.为网站定义一个队列。
1.使用Crawler线程定义池。
1.主进程遍历网站队列并检索网站地址。
1.从线程池中调用一个可用线程-为它分配网站地址并允许它开始运行。在线程对象中设置一个指示器,它应该等待所有后续线程完成(这样您就不会继续到下一个站点)。
1.一旦所有的线程都结束了-主线程(在步骤#4中开始)将结束并返回到主进程的主循环以继续到下一个网站。
Crawler的行为应该是这样的:
1.调查当前地址的内容
1.将层次结构重定向到当前级别之下
1.对于站点树的当前节点的每个子节点-从池中提取一个新的crawler线程,并使用子节点的地址在后台启动它
1.如果池为空,则等待线程变为可用。
1.如果线程被标记为等待-等待所有其他线程完成
我认为这里有一些挑战-但作为一个一般的流程,我相信它可以做的工作。

jqjz2hbq

jqjz2hbq4#

把你所有的网址放在一个队列里,每次你处理完前一个网址的时候,从队列中弹出一个。
您还可以将递归链接放在队列中,以便更好地控制一次执行的下载数量。
你可以设置X个工作线程,它们都从队列中获取一个URL,以便一次处理更多的URL。但这样你就可以自己控制了。
你可以在.Net中使用ConcurrentQueue<T>来获得一个线程安全队列。

相关问题