Search code examples
c#multithreadingbackgroundworkerthreadpool

Threadpool queue stalling on 10th item


I'm having a problem with my test application. I'm running a win form application which can post requests to a web service. There is a timer which periodically adds items to the queue of requests. I have a class called AutoManager which is used to pick items off the queue and send them off to the web service.

In TryKickQueue() it adds an IAutoProcessor onto the threadpool queue. Once the IAutoProcessor is finished it calls back to the AutoManager to remove itself from the queue.

This works fine and runs the first 10 requests no problem however for some reason I can't figure out the 10th thread never finishes and so it gets stuck. It's weird because it is always the 10th. Am I doing something wrong, should I be cleaning things up?

Should this happen or is it probably a deadlock that i've not been able to find?

Many thanks Neil

    public AutoManager(Settings _settings, Log _log)
    {
        m_sessionKicker = new BackgroundWorker();
        m_sessionKicker.DoWork += SessionKickerDoWork;
        m_sessionKicker.RunWorkerCompleted += SessionKickerRunCompleted;
        m_sessionKicker.WorkerSupportsCancellation = true;
        m_sessionKicker.RunWorkerAsync();

        m_processorQueue = new List<IAutoProcessor>();
        m_inProcessingQueue = new List<IAutoProcessor>();
    }

    private void SessionKickerDoWork(object sender, DoWorkEventArgs e)
    {
        bool bFinished = false;

        while (!bFinished)
        {
            TryKickQueue();
        }
    }

    private void TryKickQueue()
    {
        object thisObject = new Object();

        lock (thisObject)
        {
            if (m_processorQueue.Count > 0 && m_inProcessingQueue.Count < m_settings.MaxThreads)
            {
                IAutoProcessor proc = m_processorQueue[0];
                m_inProcessingQueue.Add(proc);
                m_processorQueue.RemoveAt(0);

                if (proc != null)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(proc.SendData));
                }
            }
        }
    }

    public void OnRemoveAutoProcessor(IAutoProcessor _autoProcessor)
    {
        object thisObject = new Object();

        lock (thisObject)
        {
            m_inProcessingQueue.Remove(_autoProcessor);
        }
    }

Solution

  • Your lock around the use of m_processorQueue is invalid. You're locking om the local variable thisObject but that means each thread has its own lock-object and they will never wait...

    Declare thisObject so that it has the same scope and lifetime as m_processorQueue.

    But I also note that your bgw does a busy loop, it will consume a lot of CPU time. You need some mechanism to wait on an empty queue.

    If you are using Fx4 then use the ConcurrentQueue. Otherwise look for a good implementation of a queue.