該類用於獲取URL列表,掃描它們,然後返回那些不起作用的列表。它使用多個線程來避免在長列表上永遠佔用。併發硬盤故障<T> in .net c#4
我的問題是,即使我用一個測試函數替換所有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;
}
}
'ConcurrentStack queue' - 你不使用'ConcurrentQueue',而是有一個名爲'queue'堆什麼特別的原因? –
AakashM
呵呵,不是真的。我只是快速地閱讀併發命名空間,並知道堆棧的行爲,所以我認爲這是出於熟悉我猜。它應該仍然工作。 – Toodleey