OutOfMemory Exception C # При работе с потоками - PullRequest
4 голосов
/ 30 декабря 2011

У меня есть служба, которая должна работать вечно, чтобы контролировать один сервер. Для этого у меня есть 5 задач, которые должны быть выполнены службой (5 на данный момент будут сотнями).

Я создал пул потоков максимум с 5 потоками. Существует очередь, которую потоки используют для получения задачи, затем каждый поток обрабатывает задачу, а затем снова ставит ее в очередь. Очередь содержит объекты с 5 небольшими атрибутами.

После того, как служба работает некоторое время, я получаю исключение OutOfMemoryException в строке, где я выполняю это:

ThreadPool.QueueUserWorkItem(currentJob.ProcessJob, (object)timeToWwait);

timeToWwait - это int, и я им больше не пользуюсь.

Контекст такой:

        ThreadPool.SetMinThreads(0, 0);
        ThreadPool.SetMaxThreads(5, 5);
        while (true)
        {
            bool processJob = false;
            bool checkedFrontEnd = false;
            _qLock.EnterWriteLock();
            try
            {
                if (_jobQueue.Count > 0)
                {
                    currentJob = _jobQueue.Dequeue();
                    // currentJob.IsActive = true;
                    // processJob = true;
                }
            }
            finally
            {
                _qLock.ExitWriteLock();
            }
            ThreadPool.QueueUserWorkItem(currentJob.ProcessJob, (object)timeToWwait);
            //currentJob.ProcessJob((object)timeToWwait);


            _qLock.EnterWriteLock();
            try
            {
                _jobQueue.Enqueue(currentJob);
            }
            finally
            {
                _qLock.ExitWriteLock();
            }

У вас есть предложения, пожалуйста?

Ответы [ 2 ]

2 голосов
/ 30 декабря 2011

Ваша проблема в том, что вы ставите в очередь экземпляр currentJob до того, как фоновая задача успела завершиться. Вместо этого вы захотите сделать что-то вроде этого:

        ThreadPool.QueueUserWorkItem((state) =>
                                         { 
                                             currentJob.ProcessJob();
                                             _qLock.EnterWriteLock();
                                             try
                                             {
                                                 _jobQueue.Enqueue(currentJob);
                                             }
                                             finally
                                             {
                                                 _qLock.ExitWriteLock();
                                             } 

                                         }
            );
1 голос
/ 30 декабря 2011

Похоже, что вы захотите снова поставить задание в очередь (в jobQueue) только после того, как оно было завершено потоком, работающим над ним.Представьте, что в пуле только 1 поток и 1 задание в jobQueue. Если задание долго выполняется, ваш код будет выполнять ThreadPool.QueueUserWorkItem много раз для одного и того же задания.Также я думаю, что вы захотите выполнить ThreadPool.QueueUserWorkItem только в том случае, если в jobQueue есть задание (из приведенного выше кода это выглядит так, как будто оно будет работать независимо).Спасибо за интересный вопрос.

...