В настоящее время я создаю веб-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();
}
}
Вместо этого я использовал бы ConcurrentDictionary. – DixonD
Очень мало нужно делать с несколькими потоками. Акт выполнения IO (предположительно через Интернет) в десятки тысяч раз медленнее, чем анализ страниц. Вы получите очень мало преимуществ, используя несколько потоков. – Enigmativity
@ DixonD - Спасибо, но это будет недостаточно, потому что мне нужен список для итерации с числовыми индексами. Предполагается, что веб-сканеры будут созданы с рекурсивным обходом, я просто нашел другой способ добавления новых ссылок в конец списка, который в настоящее время повторяется, чтобы избежать рекурсии. Вот почему я не могу переключить его на ConcurrentDictionary. Даже если я создаю файл, мне нужен еще один HashTable, чтобы избежать обхода одного веб-сайта несколько раз. –
BlueRay101