Этот класс предназначен для получения списка URL-адресов, их сканирования, а затем возврата списка тех, которые не работают.Это использует многократные потоки, чтобы избежать навсегда занять длинные списки.
Моя проблема в том, что, даже если я заменил фактическое сканирование URL-адресов на тестовую функцию, которая возвращает ошибки всех URL-адресов, класс возвращает переменное количество ошибок.Проблема заключается либо в ConcurrentStack.TryPop () или .Push (), но я не могу на всю жизнь понять, почему.Они предположительно безопасны для многопоточной обработки, и я тоже пытался их заблокировать, там никакой помощи.
Кто-нибудь может мне объяснить, что я делаю неправильно?У меня нет большого опыта работы с несколькими темами ..
public class UrlValidator
{
private const int MAX_THREADS = 10;
private List<Thread> threads = new List<Thread>();
private ConcurrentStack<string> errors = new ConcurrentStack<string>();
private ConcurrentStack<string> queue = new ConcurrentStack<string>();
public UrlValidator(List<string> urls)
{
queue.PushRange(urls.ToArray<string>());
}
public List<string> Start()
{
threads = new List<Thread>();
while (threads.Count < MAX_THREADS && queue.Count > 0)
{
var t = new Thread(new ThreadStart(UrlWorker));
threads.Add(t);
t.Start();
}
while (queue.Count > 0) Thread.Sleep(1000);
int runningThreads = 0;
while (runningThreads > 0)
{
runningThreads = 0;
foreach (Thread t in threads) if (t.ThreadState == ThreadState.Running) runningThreads++;
Thread.Sleep(100);
}
return errors.ToList<string>();
}
private void UrlWorker()
{
while (queue.Count > 0)
{
try
{
string url = "";
if (!queue.TryPop(out url)) continue;
if (TestFunc(url) != 200) errors.Push(url);
}
catch
{
break;
}
}
}
private int TestFunc(string url)
{
Thread.Sleep(new Random().Next(100));
return -1;
}
}