无限循环不断创建新线程
Endless loop keep creating new threads
我目前正在用 C# 编写一个基本的网络爬虫。它是多线程的,但在当前结构下,它会在无限循环中不断创建线程。我应该在此代码中更改什么:
抓取工具:
public static void Start(Uri url)
{
if (!RobotsParser.IsDomainParsed(LinkParser.GetDomainUrl(url)))
{
RobotsParser.Parse(url);
}
if (!CrawlQueue.CrawledList.Contains(url) && RobotsParser.IsCrawlingAllowed(url.ToString()))
{
CrawlQueue.CrawledList.Add(url);
CrawlQueue.QueueList.Remove(url);
//Crawling logic happens here...
CrawlQueue.Add(LinkParser.Find(doc, responseUri));
}
}
}
链接解析器:
public static HashSet<Uri> Find(HtmlDocument doc, string url)
{
//returns list of found urls
return list;
}
队列(这就是问题所在)
internal static class CrawlQueue
{
public static HashSet<Uri> QueueList = new HashSet<Uri>();
public static HashSet<Uri> CrawledList = new HashSet<Uri>();
private static void Start()
{
Parallel.ForEach(QueueList.ToList(), new ParallelOptions { MaxDegreeOfParallelism = 7 }, url =>
{
try { CrawlEngine.Start(url); }
catch (Exception e) { Debug.WriteLine(url + " "+ e.ToString()); }
});
}
public static void Add(HashSet<Uri> list)
{
int counter = 0;
foreach (var site in list.Where(site => !QueueList.Contains(site)))
{
QueueList.Add(site);
counter++;
}
if (counter >= 1)
{
Logging.Log(counter + " items added to crawling queue");
Start();
}
}
}
在浏览列表时我应该进行哪种设计?
产生许多线程的问题是对 Start()
的递归调用与 Parallel.ForEach
相结合(阻塞调用)。您应该改用 Task.Factory.StartNew()
之类的东西,以允许在子任务为 运行 时退出对 Start()
的调用。您可能还需要重构您的代码以 return 结果任务,以便您可以知道什么时候完成。
如评论所述,您可能不需要阻塞多线程解决方案(您应该使用非阻塞 IO),但这是一个更大的变化。
我目前正在用 C# 编写一个基本的网络爬虫。它是多线程的,但在当前结构下,它会在无限循环中不断创建线程。我应该在此代码中更改什么:
抓取工具:
public static void Start(Uri url)
{
if (!RobotsParser.IsDomainParsed(LinkParser.GetDomainUrl(url)))
{
RobotsParser.Parse(url);
}
if (!CrawlQueue.CrawledList.Contains(url) && RobotsParser.IsCrawlingAllowed(url.ToString()))
{
CrawlQueue.CrawledList.Add(url);
CrawlQueue.QueueList.Remove(url);
//Crawling logic happens here...
CrawlQueue.Add(LinkParser.Find(doc, responseUri));
}
}
}
链接解析器:
public static HashSet<Uri> Find(HtmlDocument doc, string url)
{
//returns list of found urls
return list;
}
队列(这就是问题所在)
internal static class CrawlQueue
{
public static HashSet<Uri> QueueList = new HashSet<Uri>();
public static HashSet<Uri> CrawledList = new HashSet<Uri>();
private static void Start()
{
Parallel.ForEach(QueueList.ToList(), new ParallelOptions { MaxDegreeOfParallelism = 7 }, url =>
{
try { CrawlEngine.Start(url); }
catch (Exception e) { Debug.WriteLine(url + " "+ e.ToString()); }
});
}
public static void Add(HashSet<Uri> list)
{
int counter = 0;
foreach (var site in list.Where(site => !QueueList.Contains(site)))
{
QueueList.Add(site);
counter++;
}
if (counter >= 1)
{
Logging.Log(counter + " items added to crawling queue");
Start();
}
}
}
在浏览列表时我应该进行哪种设计?
产生许多线程的问题是对 Start()
的递归调用与 Parallel.ForEach
相结合(阻塞调用)。您应该改用 Task.Factory.StartNew()
之类的东西,以允许在子任务为 运行 时退出对 Start()
的调用。您可能还需要重构您的代码以 return 结果任务,以便您可以知道什么时候完成。
如评论所述,您可能不需要阻塞多线程解决方案(您应该使用非阻塞 IO),但这是一个更大的变化。