C#多线程代理检查器
所以有了一个新问题 我正在用c#编写一个多线程proxychecker 我正在使用BackgroundWorkers来解决多线程问题 但我在协调并将队列中的代理分配给正在运行的工作人员时遇到了问题。它在大多数情况下都能工作,但有时不会返回结果,因此某些代理在过程中会“丢失” 此列表表示队列,并在ListView中填充代理的IDC#多线程代理检查器,c#,multithreading,listview,backgroundworker,C#,Multithreading,Listview,Backgroundworker,所以有了一个新问题 我正在用c#编写一个多线程proxychecker 我正在使用BackgroundWorkers来解决多线程问题 但我在协调并将队列中的代理分配给正在运行的工作人员时遇到了问题。它在大多数情况下都能工作,但有时不会返回结果,因此某些代理在过程中会“丢失” 此列表表示队列,并在ListView中填充代理的ID private List<int> queue = new List<int>(); private int GetNextinQueue()
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;
}
私有列表队列=新列表();
private int GetNextinQueue()
{
如果(queue.Count>0)
{
锁(锁队列)
{
int temp=队列[0];
队列移除(临时);
返回温度;
}
}
其他的
返回-1;
}
上面是我获取队列中下一个代理的方法,我使用lock语句来防止竞争条件,但我不确定这是否足够,或者它是否会减慢进程,因为它会使其他线程等待。。。
(lockqueue是仅用于锁定的对象)
所以我的问题是,有些代理怎么可能没有被检查(即使ping失败,检查应该会返回一些东西,但有时什么都没有),我如何优化代码以提高性能
下面是剩下的代码,我认为这个问题很重要。
如果缺少什么,就写一条评论
谢谢:)有几件事:
queue
字段的所有访问都需要进入lock(lockqueue)
块中——这包括上面的if(queue.Count>0)
行。这不是性能问题:如果不在需要的地方获取锁,应用程序将无法工作RunWorkerAsync
的调用看起来可疑。当前,每个BackgroundWorker
共享相同的参数数组;你需要给每个人一份自己的副本应在lock语句中执行对queue.Count的检查。Otberwise您可以检查该队列。计数>0,但是当您能够进入锁时,另一个线程可能已经从队列中删除了一个项目,然后您将在可能为空的队列上调用Remove 您可以将其修改为:
private int GetNextinQueue()
{
lock (lockqueue)
{
if(queue.Count > 0)
{
int temp = queue[0];
queue.Remove(temp);
return temp;
}
else
return -1;
}
}
基本上,如果要使用锁保护对数据结构的访问,请确保保护对该结构的所有读写以确保线程安全。请尝试以下方法:
private int GetNextinQueue()
{
int ret = -1;
lock (queue)
{
if (queue.Count > 0)
{
int temp = queue[0];
queue.Remove(temp);
ret = temp;
}
}
return ret;
}
我不担心这个的性能——如果一个线程持有锁,其他线程确实会在这里阻塞,但是从列表中删除int
并不需要很长时间
此外,您实际上不需要
lockqueue
对象-因为queue
是您要锁定访问的对象,只需使用它即可。如果您对简单优雅感兴趣,请使用队列:
private Queue<int> queue = new Queue<int>();
private int GetNextinQueue()
{
lock (queue) { return queue.Count > 0 ? queue.Dequeue() : -1; }
}
private Queue=new Queue();
private int GetNextinQueue()
{
锁(队列){return queue.Count>0?queue.Dequeue():-1;}
}
“此外,您实际上不需要lockqueue对象-因为队列是您要锁定访问权限的对象,只需使用它即可。”-不要这样做;而是锁定一个单独的对象
实例。这是对可能在内部使用lock(This)
的其他类作者的一种防御。@Tim Robinson:lock(This)
将被视为糟糕的编程实践(),我怀疑List
的作者是否会这样做。MSDN的更多信息:严格来说,提供给lock的对象仅用于唯一标识多个线程之间共享的资源,因此它可以是任意类实例。然而,在实践中,这个对象通常表示线程同步所必需的资源。“我不能代表列表
类的开发人员说话,但一般来说,你不可能是安全的:(a)C#编译器本身施加锁(这)
以其生成的add\u Event
和remove\u Event
方法的形式在您身上;以及(b)您没有发现开发人员没有使用锁(此)
直到为时已晚。谢谢,这是一个非常好的解决方案。感谢所有其他人的帮助,我非常感激,但遗憾的是,我只能接受一个答案。我认为“丢失”代理的问题现在已经解决了。