Как узнать, что поток в пуле потоков зависает / зависает - PullRequest
2 голосов
/ 14 декабря 2010

У меня есть очередь задач для ThreadPool, и каждая задача имеет тенденцию заморозить блокировку всех ресурсов, которые она использует.И они не могут быть освобождены, если служба не будет перезапущена.

Есть ли способ в ThreadPool узнать, что его поток уже заморожен?У меня есть идея использовать тайм-аут (хотя я до сих пор не знаю, как его записать), но я думаю, что это небезопасно, потому что продолжительность обработки не одинакова.

Ответы [ 3 ]

3 голосов
/ 14 декабря 2010

Я не хочу быть здесь слишком самонадеянным, но хорошая попытка выяснить, в чем заключается проблема, и исправить ее - лучший путь с тупиками.

  • Запустите отладочную версию вашего сервиса и подождите, пока он не заблокируется. Он останется заблокированным, поскольку это замечательное свойство тупиков.
  • Присоедините отладчик Visual Studio к службе.
  • «Сломай все».
  • Подними окна темы и начни говорить ...

Если у вас нет здравой архитектуры / дизайна \ причины выбирать жертв в первую очередь, не делайте этого - точка. Это в значительной степени рецепт катастрофы - произвольно перебивать потоки над головой, когда они в центре чего-то.

2 голосов
/ 14 декабря 2010

(Возможно, это немного низкоуровневый, но по крайней мере это простое решение. Поскольку я не знаю API C #, это общее решение для любого языка, использующего пулы потоков.)

Вставить контрольную задачу после каждой реальной задачи, которая обновляет значение времени с текущим временем. Если это значение превышает максимальное время выполнения задачи (скажем, 10 секунд), вы знаете, что что-то застряло.

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

Лучший способ, вероятно, заключить каждую задачу в класс задач «Сторожевой», который делает это автоматически. Таким образом, по завершении вы очистите таймер и сможете установить таймаут для каждой задачи, что может быть полезно.

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

Обратите внимание, что это решение не требует от вас изменения кода ваших задач. Он только изменяет код, помещающий задачи в пул.

1 голос
/ 14 декабря 2010

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

Пусть каждый поток устанавливает значение, специфичное для потока, как минимум 1 раз в пять секунд (например).

Затем ваш сторожевой таймер включается каждые десять секунд (опять же, это только примерный рисунок) и проверяет, чтобы все значения были равны 1. Если они не 1, то поток заблокирован до.

Затем сторожевой таймер устанавливает их на 0 и переходит в спящий режим для следующего цикла.

Если ваши рабочие потоки написаны таким образом, чтобы они могли своевременно устанавливать значения в незамерзающих условиях, эта схема будет работать нормально.

Первый поток, который блокируется, не будет устанавливать свое значение в 1, и это будет обнаружено сторожевым таймером в следующем цикле.


Тем не менее, лучшее решение состоит в том, чтобы сначала выяснить, почему потоки зависают, и исправить это.

...