【发布时间】:2021-11-24 11:51:19
【问题描述】:
我很难理解多线程和并行编程。我有一个小应用程序(Scraper)。我将 Selenium 与 C# .NET 一起使用。我有一个包含企业地址的文件。然后我用我的爬虫来查找公司名称和他们的网站。之后,我根据他们的公司网站再次抓取通用电子邮件地址
这就是问题所在。如果我手动执行此操作,我需要 3 年时间才能完成 50,000 条记录。我做了数学。哈哈。这就是我创建刮板的原因。一个普通的控制台应用程序需要 5 到 6 天才能完成。然后,我决定也许使用多线程和并行编程可以减少时间。
所以,我做了一个小样本测试。我注意到 1 条记录需要 10 秒。完成。然后有 10 条记录需要 100 秒。我的问题是为什么多线程需要同样的时间?
我不确定我对多线程的期望和理解是否错误。我想通过使用Parallel.ForEach 将启动所有十个记录并在 10 秒内完成,为我节省了 90 秒。这是正确的假设吗?有人可以澄清一下多线程和并行编程的实际工作原理吗?
private static List<GoogleList> MultiTreadMain(List<FileStructure> values)
{
List<GoogleList> ListGInfo = new List<GoogleList>();
var threads = new List<Thread>();
Parallel.ForEach (values, value =>
{
if (value.ID <= 10)
{
List<GoogleList> SingleListGInfo = new List<GoogleList>();
var threadDesc = new Thread(() =>
{
lock (lockObjDec)
{
SingleListGInfo = LoadBrowser("https://www.google.com", value.Address, value.City, value.State,
value.FirstName, value.LastName,
"USA", value.ZipCode, value.ID);
SingleListGInfo.ForEach(p => ListGInfo.Add(p));
}
});
threadDesc.Name = value.ID.ToString();
threadDesc.Start();
threads.Add(threadDesc);
}
});
while (threads.Count > 0)
{
for (var x = (threads.Count - 1); x > -1; x--)
{
if (((Thread)threads[x]).ThreadState == System.Threading.ThreadState.Stopped)
{
((Thread)threads[x]).Abort();
threads.RemoveAt(x);
}
}
Thread.Sleep(1);
}
return ListGInfo;
}
【问题讨论】:
-
多线程并不总是更快。首先,您的网络延迟不会变得更短。它实际上可能会变得更糟,因为您正在增加网络连接上的流量。其次,多线程并不能提高服务器响应请求的时间——它实际上会因为服务器负载的增加而减慢它的速度。三、谷歌CPU上下文切换。
-
如果你有 CPU 密集型工作 - Parallel.ForEach,如果你有 IO(读/写 http/file/任何其他异步控制器) - 使用任务。假设您只是在抓取网站,您应该只使用 async+Task 范例(因为,在 Parallel 产生的完整的 CPU 密集型线程上无需等待 10 秒)。任务很轻,通过发回信号而不是自旋锁等待来处理来自网站的异步响应。根据我的经验,您在抓取时的主要顾虑 - 异步 + 内存池(尽可能多的 IP)
-
> 我想通过使用 parallel.Foreach 将启动所有十个记录并在 10 秒内完成,为我节省了 90 秒。是的。这个假设是正确的。如果您的代码表现不同,则说明其他问题。
-
So, I did a small sample test.我们不能评论我们看不到的代码。 -
这是 .NET Core 还是 Framework?哪个版本?控制台或网络应用程序(是的,这很重要)?
标签: c# multithreading selenium web-scraping parallel-processing