Очередь потоков пула останавливается на 10-м элементе - PullRequest
1 голос
/ 26 октября 2011

У меня проблема с моим тестовым приложением.Я запускаю приложение win form, которое может публиковать запросы в веб-сервисе.Есть таймер, который периодически добавляет элементы в очередь запросов.У меня есть класс AutoManager, который используется для выбора элементов из очереди и отправки их в веб-службу.

В TryKickQueue () он добавляет IAutoProcessor в очередь пула потоков.Когда IAutoProcessor завершается, он обращается к AutoManager, чтобы удалить себя из очереди.

Это работает нормально и без проблем запускает первые 10 запросов, однако по какой-то причине я не могу понять, что 10-й поток никогда не заканчиваетсяи так застревает.Это странно, потому что это всегда 10-е.Я делаю что-то не так, мне нужно что-то убирать?

Должно ли это случиться или это тупик, который я не смог найти?

Большое спасибо, Нил

    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);
        }
    }

Ответы [ 2 ]

2 голосов
/ 26 октября 2011

Ваша блокировка использования m_processorQueue недействительна.Вы блокируете локальную переменную thisObject, но это означает, что каждый поток имеет свой собственный объект блокировки, и они никогда не будут ждать ...

Объявите thisObject, так что он имеет ту же область действия и время жизни, что и m_processorQueue.

Но я также отмечаю, что ваш bgw делает цикл занятости, он будет занимать много процессорного времени.Вам нужен механизм ожидания в пустой очереди.

Если вы используете Fx4, используйте ConcurrentQueue.В противном случае ищите хорошую реализацию очереди.

0 голосов
/ 26 октября 2011

Переместите ваш замок (thisObject) из локального в метод из глобального в тип.

    static object thisObject = new Object();
    private void TryKickQueue() 
    { 
        lock (thisObject) 
        { 
           // your logic
        } 
    } 

    public void OnRemoveAutoProcessor(IAutoProcessor _autoProcessor) 
    { 
        lock (thisObject) 
        { 
           //your logic
        } 
    }

Не уверен, почему вы проверяете этот m_inProcessingQueue.Count < m_settings.MaxThreads.

...