所以遇到了一个新问题...
我正在用c#编写一个多线程的proxychecker。
我正在使用BackgroundWorkers来解决多线程问题。
但是我在协调并将队列中剩余的代理分配给runnning worker时遇到了问题。它大部分时间都可以工作,但有时候没有结果会回来,因此一些代理在此过程中会“丢失”。
此列表表示队列,并在ListView中填充代理的ID。
private List<int> queue = new List<int>();
private int GetNextinQueue()
{
if(queue.Count > 0)
{
lock (lockqueue)
{
int temp = queue[0];
queue.Remove(temp);
return temp;
}
}
else
return -1;
}
上面是我的方法来获取队列中的下一个代理,我正在使用lock语句来防止竞争条件,但我不确定它是否足够或者是否会减慢进程,因为它会让其他线程等待... (lockqueue是一个刚刚用于锁定的对象)
所以我的问题是,如何检查某些代理是否可能(即使ping失败,检查应该返回一些东西,但有时候什么都没有)以及我如何优化此代码以获得性能?
以下是我认为对此问题http://pastebin.com/iJduX82b
重要的其余代码如果缺少某些内容,只需撰写评论
谢谢:)
答案 0 :(得分:4)
应该在lock语句中执行queue.Count的检查。你可以检查一下queue.Count&gt; 0,但是当你能够进入锁定时,另一个线程可能已经从队列中删除了一个项目,然后你将在可能空的队列上调用Remove。
您可以将其修改为:
private int GetNextinQueue()
{
lock (lockqueue)
{
if(queue.Count > 0)
{
int temp = queue[0];
queue.Remove(temp);
return temp;
}
else
return -1;
}
}
基本上,如果要保护对具有锁定的数据结构的访问,请确保为了线程安全而保护对该结构的所有读取和写入。
答案 1 :(得分:2)
有几件事:
对queue
字段的所有访问都需要进入lock (lockqueue)
块 - 这包括上面的if (queue.Count > 0)
行。这不是性能问题:如果您在必要时没有获得锁定,您的应用程序将无法运行。
从您的pastebin,对RunWorkerAsync
的调用看起来很可疑。目前每个BackgroundWorker
共享相同的参数数组;你需要给每个人一份自己的副本。
答案 2 :(得分:2)
请改为尝试:
private int GetNextinQueue()
{
int ret = -1;
lock (queue)
{
if (queue.Count > 0)
{
int temp = queue[0];
queue.Remove(temp);
ret = temp;
}
}
return ret;
}
我不担心这个性能 - 如果一个线程持有锁,其他线程就会在这里阻塞,但是从List中删除int
并不需要很长时间。
此外,您实际上并不需要lockqueue
对象 - 因为queue
是您要锁定访问权限的对象,只需使用它即可。
答案 3 :(得分:1)
如果您对简单优雅感兴趣,请使用队列:
private Queue<int> queue = new Queue<int>();
private int GetNextinQueue()
{
lock (queue) { return queue.Count > 0 ? queue.Dequeue() : -1; }
}