1

I have an async queue processor that has a Run method which keeps running with a pause of 100ms. This code results in CPU usage of almost 100%. following the thr code of 'Run' method of this async queue processor.

        private void Run()
        {
            while (true)
            {
                if (q.Count != 0)
                {
                    ServiceMessage msg = (ServiceMessage)synchQ.Dequeue();
                    OnHeartBeat(msg.Args);
                }
                PauseTrigger.WaitOne(100, false);
            }
        }

Please let me know if there is something wrong that I am doing.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Sumee
  • 377
  • 1
  • 5
  • 12

4 Answers4

3

If queue is empty and PauseTrigger is set this will spin and use 100% CPU.

If you are using .NET 4 then BlockingCollection provides a much nicer way to handle queueing and dequeing.

Ian Mercer
  • 38,490
  • 8
  • 97
  • 133
  • 1
    Hightechrider, thanks but i am using .net 3.5. Please let me know if there is any alternative that I can use. I need a nicer and cleaner way of doing this. – Sumee Oct 25 '10 at 05:01
  • Take a look at the second answer here: http://stackoverflow.com/questions/1116249/manualresetevent-vs-thread-sleep – Ian Mercer Oct 25 '10 at 05:05
  • Or this article on MSDN: http://msdn.microsoft.com/en-us/library/yy12yx1f(VS.80).aspx – Ian Mercer Oct 25 '10 at 05:09
  • @Sumee, you can use new thread-safe collection from .NET 4 in 3.5, just download Reactive Extensions for .NET (Rx) http://bit.ly/dnHhes and reference System.Threading.dll from it (you don't need others). So you can go with nice ConcurrentQueue. – Nick Martyshchenko Oct 25 '10 at 05:45
  • @Nick, i'll then have to ship System.Threading.dll with my solution and I am not sure whether i can legally redistribute it or not. – Sumee Oct 25 '10 at 06:25
2

A simple fix would be to try Thread.Sleep (100); rather than PauseTrigger.WaitOne(100)

If it doesn't matter for you which thread OnHeartBeat is called on you can use this class.

public class ProcessingQueue<T>
{


    private readonly object _lock = new object();
    private readonly Queue<T> _queue = new Queue<T>();
    private readonly Action<T> _workMethod;
    private bool _pumpIsAlive;  

    private void Pump()
    {
        while (true)
        {

            lock (this._lock)
            {
                item = this._queue.Dequeue();
            }

            this._workMethod(item);

            lock (this._lock)
            {
                if (this._queue.Count == 0)
                {
                    this._pumpIsAlive = false;
                    break;
                }
            }
        }

    /// <summary>
    /// Pushes an item onto the processing the queue to be handled at an indeterminate time.
    /// </summary>
    /// <param name="item">The item to push onto the queue.</param>
    public void Push(T item)
    {
        lock (this._lock)
        {
            this._queue.Enqueue(new Containter(item));
            this.StartPump();
        }
    }

    private void StartPump()
    {
        lock (this._lock)
        {
            if (!this._pumpIsAlive)
            {
                this._pumpIsAlive= true;
                ThreadPool.QueueUserWorkItem(o => this.Pump());
            }
        }
    }

which you could then use like:

var q = new ProcessingQueue<ServiceMessage> ( sm => OnHeartBeat(sm.args));

q.Push (new ServiceMessage (someArgs));
1

OnHeartBeat(msg.Args) takes longer than 100ms to complete?

Why not run your code in a profiler to find out where the CPU cycles are being spent?

See this question: Any Good Free .NET Profiler?

Community
  • 1
  • 1
spender
  • 117,338
  • 33
  • 229
  • 351
  • 1
    I don't think so. Even if it takes longer than 100ms, it shouldn't matter because it is a synchronous call. or m i wrong? – Sumee Oct 25 '10 at 04:52
  • If it's synchronous, I agree. It's a bit of a guessing game. Profiler? – spender Oct 25 '10 at 04:56
0

2 things... why are you dequeueing synchQ while checking for q.count?

Try putting a counter and see if you are running into an infinite loop because of synchQ and q.count check

Rahul Soni
  • 4,941
  • 3
  • 35
  • 58