【发布时间】:2011-09-08 09:37:21
【问题描述】:
这个类旨在获取一个 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;
}
}
【问题讨论】:
-
ConcurrentStack<string> queue- 任何特殊原因您不使用ConcurrentQueue,而是使用名为queue的堆栈? -
呵呵不,不是真的。我只是快速阅读并发命名空间并知道堆栈的行为方式,所以我猜是出于熟悉而选择它。不过它应该仍然可以工作。
标签: c# asp.net multithreading c#-4.0 concurrency