Как узнать кто убивает мои темы - PullRequest
28 голосов
/ 20 апреля 2010

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

Мне приходит в голову, что моя нить прерывается ОС, но я хотел бы подтвердить это и, если возможно, узнать, почему это убивает ее.

Что касается потока, я могу утверждать, что до его смерти требуется не менее 40 минут, но внезапно он умирает примерно через 5 минут.

public void RunWorker()
{
    Thread worker = new Thread(delegate()
    {
        try
        {
            DoSomethingForALongLongTime();
        }
        catch(Exception e)
        {
           //Nothing is never logged :(
           LogException(e);
           throw e;
        }
    });

    worker.IsBackground = true;
    worker.SetApartmentState(System.Threading.ApartmentState.STA);
    worker.Start();
}

РЕДАКТИРОВАТЬ: Адресация ответов

  • Try / Catch Возможные исключения:
    Он реализован и ничего не ловит: (
  • Основная нить умирает:
    Этот поток создан веб-сервером, который продолжает работать
  • Завершение работы:
    Работа не завершена, так как она, наконец, влияет на базу данных, я могу проверить, выполнено ли это, когда поток умирает.

Размышления об этих вещах привели меня к этому вопросу: кто убивает мои темы?

пс. Это не леди Голдент в гостиной с подсвечником :) 1023 *

Ответы [ 15 ]

20 голосов
/ 12 мая 2010

Различные люди (включая меня, здесь ) указали, что хостинг долго работающего потока в IIS - плохая идея. Ваш поток будет работать внутри «рабочего процесса» IIS. Эти процессы периодически завершаются (перерабатываются) IIS, что приводит к потере потока.

Я предлагаю вам попробовать отключить утилизацию рабочих процессов IIS, чтобы увидеть, если это что-то изменит. Вы можете найти более подробную информацию здесь .

13 голосов
/ 20 апреля 2010

Ваша тема, вероятно, только что выбросила исключение. Попробуйте поставить блок try / catch вокруг DoSomethingForALongLongTime и посмотрите, что он подхватит.


Обновление: Я раньше не замечал, что вы запускаете это с веб-сервера. Это может быть очень плохой идеей. В частности, использует ли отдельный поток какую-либо информацию, полученную из HttpContext.Current? Это будет включать Request, Response, Session и т. Д., А также любую информацию со страницы.

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

Если вам нужно запустить длительный поток из веб-приложения или веб-службы, то вам следует создать простую службу Windows и разместить в ней службу WCF. Сделайте так, чтобы веб-страница отправила всю информацию, необходимую для выполнения задачи, в службу. Служба может даже использовать MSMQ в качестве транспорта, который гарантирует, что никакие сообщения не будут потеряны, даже если служба будет занята.

5 голосов
/ 07 мая 2010

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

  1. Скачать Средства отладки для Windows , если у вас его еще нет
  2. Запустите windbg.exe, прикрепите к вашему процессу
  3. Break to windbg, введите sxe et, чтобы разрешить разрыв при выходе из нити
  4. Когда отладчик выходит из строя, проверять состояние системы, других потоков и т. Д.
  5. Чтобы получить управляемый стек, загрузите sos.dll (.loadby sos mscorsvr, .loadby sos mscorwks или .loadby sos clr должно работать), затем запустите !clrstack (другие команды sos см. В !help)

Если вы слышите много шума при выходе из других потоков, скрипт windbg продолжит работу после разрыва, если вам нужен не идентификатор потока.

Редактировать: Если вы думаете, что поток прерывается изнутри вашего процесса, вы также можете установить точку останова на TerminateThread (bp kernel32!TerminateThread) и ExitThread (bp kernel32!ExitThread) для перехвата стек убийцы.

4 голосов
/ 20 апреля 2010

Ваша правка показывает ответ:

Это дворецкий веб-сервер.

Как именно вы размещаете эти темы? Среда веб-сервера не предназначена для размещения долгоживущих процессов. Фактически, он, вероятно, настроен для остановки сбежавших сайтов, может быть, каждые 40 минут?

Edit:
Для быстрого исправления ваш лучший шанс - установить worker.IsBackground = false;, потому что ваш текущий параметр true позволяет системе уничтожать родительский поток без ожидания вашего bgw.

С другой стороны, нет смысла использовать BackgroundWorker в приложении ASP.NET, оно предназначено для WinForms и WPF. Для этого было бы лучше создать отдельный поток, так как вы изменяете некоторые свойства потоков. Это не рекомендуется для потока ThreadPool (Bgw).

4 голосов
/ 20 апреля 2010

Я не знаю ответа, но некоторые мысли:

  • Может ли это быть исключением? Вы пытались сделать попытку / поймать вызов DoSomethingForALongLongTime ()?
  • Есть ли точки, где он обычно выходит? Попробуйте поставить на них логи.
  • Вы получаете одинаковое поведение в отладчике и из него? Предоставляет ли окно вывода в отладчике какие-либо подсказки?

UPDATE

Вы сказали:

Эта тема создана в сети сервер, который продолжает работать

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

3 голосов
/ 20 апреля 2010

Фоновый поток будет работать только до тех пор, пока выполняются потоки переднего плана.

Как только все потоки переднего плана заканчиваются, все фоновые потоки, все еще работающие, будут прерваны.

3 голосов
/ 20 апреля 2010

Процесс может быть прекращен. Это было бы то, что работник. IsBackground = true; предназначен, чтобы сделать, убить ваш поток, когда основной поток выходит.

2 голосов
/ 12 мая 2010

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

List runningThreads = ...
public void RunWorker() {
    Thread worker = new Thread(delegate()
    ..
    runningThreads.add(worker);
    worker.Start();
}

public void checkThreads() {
 for (Thread t : runningThreads) {
   Console.WriteLine("ThreadState: {0}", t.ThreadState);
 }
}
2 голосов
/ 06 мая 2010

Можно попытаться увеличить executeTimeout значение configuration \ system.web \ httpRuntime в web.config (значение по умолчанию - 110 секунд в .NET 4.0 и 90 в соответствует http://msdn.microsoft.com/en-us/library/e1f13641.aspx). Вы можете попытаться изменить его динамически Server.ScriptTimeout = 300 (см. http://www.beansoftware.com/ASP.NET-Tutorials/Long-Operations.aspx). Если этот параметр не поможет, то, я думаю, у вас возникла проблема, связанная с перезапуском потока из IIS. Как вы можете видеть значение по умолчанию для этого параметра, намного меньше, чем типичное время жизни вашего потока. Я думаю, что ваша проблема имеет другую природу, но, чтобы быть уверенным ...

Почему вы устанавливаете состояние квартиры для потока? Какие COM-объекты вы используете в рабочем потоке? У вас есть неуправляемый код, который выполняет большую часть работы, где вы также можете вставить некоторый код? Я думаю, вам нужно больше информации о SomethingForALongLongTime, чтобы решить проблему.

И еще одно маленькое предложение. Не могли бы вы вставить строку кода после вызова SomethingForALongLongTime();, чтобы убедиться, что SomethingForALongLongTime не закончится без исключения?

ОБНОВЛЕНО: Чтобы быть абсолютно уверенным, что ваш поток не будет уничтожен IIS, вы можете попытаться создать процесс, выполняющий SomethingForALongLongTime(); вместо использования потоков.

2 голосов
/ 20 апреля 2010

Простой ответ: «Убийца не оставляет карточку с именем»;)

  • Если ваш поток размещен в IIS, возможно, поток прерывается процессом пула приложений, который перезагружается. Сервер может продолжить работу, но процесс, в котором размещен ваш элемент, остановлен, пока новый запрос не запустит все снова.
  • Если ваш поток размещен в исполняемом файле, единственный способ его уничтожить - это убить его самостоятельно, вызвать исключение в потоке или завершить хост-процесс

Надеюсь, это поможет.

...