2015-01-31 2 views
3

В настоящее время я создаю веб-Crawler на C#, и у меня есть метод, который получает строки HTML, извлекает ссылки из них и вставляет ссылки в список всех захваченных ссылок.Замки C# - Лучше ли блокировать перед петлей или внутри нее?

Поскольку это многопоточность, я использовал блокировки, чтобы исключить доступ к списку всех строк из нескольких разных потоков одновременно.

Что лучше делать с замками?

Это:

void ProcessHTML(string HTML) 
{ 
    List<string> Links = GetLinks(HTML); 
    for (int i = 0; i < Links.Count; i++) 
    { 
     lock (WebsitesHash) 
     { 
      lock (AllLinks) 
      { 
        if (!WebsitesHash.ContainsKey(Links[i])) 
        { 
         WebsitesHash[Links[i]] = true; 
         AllLinks.Add(Links[i]);      
        } 
      } 
     } 
    } 
} 

Или это:

void ProcessHTML(string HTML) 
{ 
    List<string> Links = GetLinks(HTML); 
    lock (WebsitesHash) 
    { 
     lock (AllLinks) 
     { 
      for (int i = 0; i < Links.Count; i++) 
      { 
        if (!WebsitesHash.ContainsKey(Links[i])) 
        { 
         WebsitesHash[Links[i]] = true; 
         AllLinks.Add(Links[i]); 
        } 
      } 
     } 
    } 
} 

, который обычно считается лучше делать - замок на каждой итерации, или заблокировать все итерации?

Другой код, который может иметь отношение:

void StartCrawl(string Seed) 
{ 
    AllLinks.Capacity = 1000 * 1000 * 10; 
    StreamWriter Log = new StreamWriter(File.Open("Websites.txt", FileMode.Append)); 
    string HTML = GetHTML(Seed); 
    ProcessHTML(HTML); 
    for (int i = 0; i < AllLinks.Count; i++) 
    { 
     if (!Work) 
     { 
      Log.Close(); 
      WebsitesHash = new Dictionary<string, bool>(); 
      break; 
     } 
     Log.WriteLine(AllLinks[i]); 
     websText.Text = AllLinks.Count + ""; 
     try { HTML = GetHTML(AllLinks[i]); } 
     catch { continue; } 
     Thread Parser = new Thread(() => ProcessHTML(HTML)); 
     Parser.Start(); 
    } 
} 
+1

Вместо этого я использовал бы ConcurrentDictionary. – DixonD

+1

Очень мало нужно делать с несколькими потоками. Акт выполнения IO (предположительно через Интернет) в десятки тысяч раз медленнее, чем анализ страниц. Вы получите очень мало преимуществ, используя несколько потоков. – Enigmativity

+0

@ DixonD - Спасибо, но это будет недостаточно, потому что мне нужен список для итерации с числовыми индексами. Предполагается, что веб-сканеры будут созданы с рекурсивным обходом, я просто нашел другой способ добавления новых ссылок в конец списка, который в настоящее время повторяется, чтобы избежать рекурсии. Вот почему я не могу переключить его на ConcurrentDictionary. Даже если я создаю файл , мне нужен еще один HashTable, чтобы избежать обхода одного веб-сайта несколько раз. – BlueRay101

ответ

2

В этом случае, это не будет иметь значения, много.

Ссылки удаляются за пределами блокировки, поэтому единственное действие - добавление нескольких строк в список. Это очень мало, поэтому вопрос спорный.

Если объем работы был больше, то блокировка внутри петли была бы предпочтительной.

И хотя замки дешевы, вы можете немного оптимизировать, заблокировав только один раз. Вы можете использовать private object lockObject = new object(); для более четкого описания протокола.

1

Пусть AllLinks глобальное хранилище ссылок:

public List<string> AllLinks = new List<string>(); 

Список использования. BinarySearch метод где-то в коде для добавления новой ссылки:

// "link" contain string of html link 
lock(AllLinks) 
{ 
    int index = AllLinks.BinarySearch(link); 
    if(index < 0) 
    { // link is not in AllLinks 
     AllLinks.Add(~index, link); 
    } 
    else 
    { // link exist, "index" contain its position in list 
     // ... 
    } 
} 

Я думаю, что объект WebsitesHash не является необходимым.

UPD Дополнительным преимуществом использования BinarySearch является отсортированное состояние AllLinks.

+0

Ничего себе, спасибо большое! Я понятия не имел Список имел такой метод. Абсолютно лучше, чем использование HashTable, еще раз спасибо. – BlueRay101

+0

Добро пожаловать%)))))) –

 Смежные вопросы

  • Нет связанных вопросов^_^