使工作线程等待任务的最有效CPU方法是什么?

时间:2010-01-14 06:51:07

标签: c# .net multithreading synchronization

在我当前的C#/ NET 3.5应用程序中,我有一个任务队列(线程安全),我有5个工作线程,必须不断查找队列中的任务。如果任务可用,任何一个工作人员都会使任务出列并采取必要的操作。

我的工作线程类如下:

public class WorkerThread
{
    //ConcurrentQueue is my implementation of thread safe queue
    //Essentially just a wrapper around Queue<T> with synchronization locks
    readonly ConcurrentQueue<CheckPrimeTask> mQ; 
    readonly Thread mWorker;
    bool mStop;

    public WorkerThread (ConcurrentQueue<CheckPrimeTask> aQ) {
        mQ = aQ;
        mWorker = new Thread (Work) {IsBackground = true};
        mStop = false;
    }

    private void Work () {
        while (!mStop) {
            if (mQ.Count == 0) {
                Thread.Sleep (0);
                continue;
            }

            var task = mQ.Dequeue ();
            //Someone else might have been lucky in stealing
            //the task by the time we dequeued it!!
            if (task == null) 
                continue;

            task.IsPrime = IsPrime (task.Number);
            task.ExecutedBy = Thread.CurrentThread.ManagedThreadId;
            //Ask the threadpool to execute the task callback to 
            //notify completion
            ThreadPool.QueueUserWorkItem (task.CallBack, task);
        }
    }

    private bool IsPrime (int number) {
        int limit = Convert.ToInt32 (Math.Sqrt (number));
        for (int i = 2; i <= limit; i++) {
            if (number % i == 0)
                return false;
        }

        return true;
    }

    public void Start () {
        mStop = false;
        mWorker.Start ();
    }

    public void Stop () {
        mStop = true;
    }
}

问题是当队列为空时,它会消耗太多的CPU(接近98%)。我尝试使用AutoResetEvent来通知工作人员队列已被更改。所以他们有效地等待该信号设定。它已经将CPU降至接近0%,但我不完全确定这是否是最好的方法。你能建议一个更好的方法来保持线程空闲而不影响CPU的使用吗?

4 个答案:

答案 0 :(得分:7)

查看BlockingQueue的此实施方案。如果队列为空,则使用Monitor.Wait()将线程置于休眠状态。添加项目时,它使用Monitor.Pulse()来唤醒正在空队列中休眠的线程。

另一种技术是使用semaphore。每次将项添加到队列时,请调用Release()。如果需要队列中的项目,请调用WaitOne()。

答案 1 :(得分:2)

您的Work方法中目前有Thread.Sleep(0),其中没有队列项。将其更改为大于0的任何,您的CPU使用率将下降。请尝试10开头......

答案 2 :(得分:0)

您可以考虑几个选项。

一种方法是在循环期间放置一个小线程休眠。这基本上会将CPU使用率降低到0,这是相当标准的做法。

另一种方法是在评论中使用Mitch Wheat建议的重置(自动或手动)。

您还可以设计某种线程休眠一段时间的IdleTask,如果您的队列为空,只需处理IdleTask(将线程休眠)。

答案 3 :(得分:0)

如果您的队列是线程安全的,那么您不需要这样做......

    //Someone else might have been lucky in stealing 
    //the task by the time we dequeued it!! 
    if (task == null)  
        continue; 
相关问题