Task.Factory.StartNew не выполняет задачу при развертывании

У меня здесь есть некоторый код, который работает, как и ожидалось, когда я устанавливаю/запускаю его на своем компьютере, Windows 7, но когда я запускаю его на других серверах (2003 и 2008), он не работает. Код взят из библиотеки служб .NET4 WCF, которую я использую в службе Windows. Вот, упрощенно.

public void monitorQueueAndDoStuff() {
  MonitorRetryQueue();
  MonitorMainQueue();                
}

private void MonitorMainQueue() {
  Log.Info("MonitorMainQueue called");
  Task.Factory.StartNew(() =>
  {
    Log.Info("new thread monitoring queue");
    // ...NMS stuff

        while (!stopped) {
          ITextMessage mess = null;
            mess = blockingMessageCollection.Take();
            sendToQueue(mess);
        }
      }
    }
  });
}


private void MonitorRetryQueue() {
  Task.Factory.StartNew(() =>
  {
    //...NMS stuff
        consumer.Listener += new MessageListener(OnRetryErrorMessage);
        Log.Info("new thread monitoring second queue");

        //need to be constantly up for the consumer to hang around
        while (!stopped) {
          Thread.Sleep(1000);
        }
      }
    }
      });
}

Потоки должны войти в циклы, чтобы выполнить некоторую работу. Основной блокирует BlockingCollection. Теперь он создает обе задачи, но входит только во вторую и никогда не печатает в журнале «новую очередь мониторинга потоков». Я не могу понять, почему нет. Я попробовал удаленную отладку, но, поскольку она никогда не вводит код, я не увидел ничего ценного.

Я не нашел ничего, что могло бы изменить поведение кода на развернутом сервере. Кто-нибудь здесь может иметь ключ? Любые настройки в проекте Visual Studio?


person ejpb    schedule 17.08.2012    source источник


Ответы (3)


Иногда такое поведение указывает на перегрузку ThreadPool.

Поскольку это длительные/блокирующие задачи, их не следует планировать для запуска в ThreadPool, куда Task.Factory.StartNew будет отправлять их, используя TaskScheduler по умолчанию.

IMO, Task.Factory.StartNew, вероятно, не лучше всего подходит для этого, и вам лучше раскрутить свои собственные потоки для запуска этих циклов.

ThreadStart action=()=>{
    //do your thing
};
Thread thread=new Thread(action){IsBackground=true};
thread.Start();
person spender    schedule 17.08.2012
comment
Я должен согласиться, не обязательно потому, что ThreadPool перегружен, но больше, что задачи и пул потоков предназначены для использования вещами, которые не будут работать «вечно» (произвольное количество времени), как это, но вместо этого вещи у которого будет некоторое конечное количество времени, необходимое для завершения действия. Когда у вас есть некоторый цикл обработки, который вы хотите запускать «навсегда» (пока он не будет остановлен), тогда это хорошо подходит для выделенного фонового потока (так же, как некоторые приложения/фреймворки будут иметь выделенный цикл для перекачки сообщений) - person James Manning; 17.08.2012
comment
Спасибо, я ожидал, что это может помочь, но я боюсь, что это вело себя так же с ThreadStart. Приятно знать, что Task.Factory.StartNew не подходит. - person ejpb; 20.08.2012
comment
Ну, я нашел, это не имело никакого отношения к этим методам. Это была необходимая dll, которую я не настроил для локального копирования. Я не видел никаких сообщений об этом, пока не попробовал версию для командной строки. Я установил ваш ответ как правильный. - person ejpb; 22.08.2012
comment
То же самое случилось со мной, я изменил задачу на нить, это сработало как шарм :) - person Sawan; 20.12.2014
comment
Как проверить вручную или программно, не перегружен ли пул потоков? - person Markus; 02.07.2019

Распечатываются ли какие-либо сообщения журнала в журнале? Вы видите, что "MonitorMainQueue called" печатается? Как узнать, что вторая задача запущена, а первая нет? Может ли быть проблема с разрешением при создании/записи в файл журнала?

Изменить: Кроме того, в ответ на то, что @spender сказал о длительных задачах, существует перегрузка для запуска задачи с этой опцией.

Task.Factory.StartNew(MonitorMainQueue, TaskCreationOptions.LongRunning);

person Paccc    schedule 17.08.2012
comment
Основная часть этого ответа должна быть комментарием к исходному вопросу. - person spender; 17.08.2012
comment
Я согласен, но у меня недостаточно очков репутации, чтобы оставить комментарий. :) - person Paccc; 17.08.2012
comment
Да, в журнале печатается "MonitorMainQueue called", но больше ничего из этого потока, только из другого (я удалил оператор журнала во втором потоке из моего примера, сейчас верну его). Оба пишут в один и тот же журнал, так что это не имеет значения. В моей системе в журнале есть все три утверждения. Пробовал TaskCreationOptions.LongRunning без разницы. - person ejpb; 20.08.2012

У меня была такая же проблема при развертывании в моей производственной среде.

Проблема возникла из-за идентификатора, используемого пулом приложения.

По умолчанию он использовал applicationPoolIdentity с ограниченными правами.

Мы изменили на «Сетевая служба», и это сработало.

Примечание. Я не говорю, что использование NetWorkService — лучшее решение, но это явно проблема прав безопасности.

person Jenzo    schedule 29.07.2014