C#多线程代理检查器

时间:2010-06-28 12:06:50

标签: c# multithreading listview backgroundworker

所以遇到了一个新问题...

我正在用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

重要的其余代码

如果缺少某些内容,只需撰写评论

谢谢:)

4 个答案:

答案 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)

有几件事:

  1. queue字段的所有访问都需要进入lock (lockqueue)块 - 这包括上面的if (queue.Count > 0)行。这不是性能问题:如果您在必要时没有获得锁定,您的应用程序将无法运行。

  2. 从您的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; }
    }