关于 C# 中并行化的几个问题

本文关键字:几个问题 并行化 关于 | 更新日期: 2023-09-27 18:35:08

我正在用 c# 编写一个繁重的网页抓取器。我希望它快速可靠。Parallel.Foreach 和 Parallel.For 对于这个来说太慢了。对于输入,我使用的是 URL 列表。我希望有多达 300 个线程同时工作(我的 CPU 和网络连接可以处理这个问题)。最好的方法是什么?使用任务会更好地工作吗?有时线程会无缘无故地结束,并且某些结果不会保存。我想要一种更可靠的方法来做到这一点。有什么想法吗?我想要一个更可靠的队列类型的抓取。我想出了什么(不是所有代码,而是重要部分):

        List <string> input = // read text file
        int total = words.Length;
        int maxThreads = 300;
        while (true)
        {
            if (activeThreads < maxThreads)
            {
               current++;
               Thread thread = new Thread(() => CrawlWebsite(words[current]));
               thread.Start();
            }
        }
        public static void CrawlWebsite(string word)
        {
            activeThreads++;
            // scraping part
            activeThreads--;
        }

关于 C# 中并行化的几个问题

考虑使用 System.Threading.ThreadPool。对于具有许多线程的方案,它可能会更快一些,并且您不需要管理 activeThreads。相反,您可以使用 ThreadPool.SetMaxThreads() 和 SetMinThreads(),ThreadPool 为您管理并行线程的数量。

顺便说一句,您的示例中缺少共享变量的同步。同步访问的方法之一是使用"锁定" - 请参阅 http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx

此外,您的线程运行方法 - CrawlWebsite() 应该处理 ThreadAbortException - 请参阅 http://msdn.microsoft.com/en-us/library/system.threading.threadabortexception.aspx。

我最近在研究非常相似的问题,并且不认为使用任何大量线程会使它更快。最慢的想法通常是下载数据。拥有大量线程并不能使其更快,因为大多数情况下,它们都在等待网络连接数据传输等。所以我最终有两个队列。一个由一些少量线程处理,这些线程只发送异步下载请求(一次 10-15 个请求)。响应存储在另一个队列中,该队列进入另一个线程池,该线程池负责解析和数据处理(此处的线程数取决于您的 CPU 和处理算法)。

我还将所有下载的数据保存到数据库中。每当我想从 Web 实现对一些新信息的解析时,我不需要重新下载内容,而只需从数据库解析缓存的 Web(这节省了大量时间)