2015-12-16 21 views
1

我目前正在C#中编写一个基本的webcrawler。它是多线程的,但是使用当前的结构,它始终在无限循环中创建线程。无尽循环继续创建新主题

履带:我应该在此代码更改

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)); 
      } 
     } 
    } 

LinkParser:

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(); 
     } 
    } 
} 

对于什么样的我应该在设计清单时进行设计吗?

+2

您可能不需要超过单个线程,因为绝大多数工作都是IO绑定。 – Servy

+0

为什么首先使用多线程? – Maarten

回答

2

许多线程产生的问题是递归调用Start()加上Parallel.ForEach(阻塞调用)。您应该使用类似Task.Factory.StartNew()的东西,以便在子任务运行时允许呼叫Start()退出。您可能需要重构代码以返回结果任务,以便您可以知道何时完成所有事情。

正如评论提到的,你可能不需要阻塞多线程解决方案(你应该使用非阻塞IO),但这是一个更大的变化。