Как узнать кто убивает мои темы

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

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

Что касается потока, я могу утверждать, что у него есть по крайней мере 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 Возможные исключения:
    Это реализовано и ничего не ловит:(
  • Основная тема умирает:
    Этот поток создан веб-сервером, который продолжает работать
  • Завершение работы:
    Работа не завершена, так как она, наконец, влияет на базу данных, я могу проверить, сделана она или нет, когда поток умирает.

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

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

15 ответов

Решение

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

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

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


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

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

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

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

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

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

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

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

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

ОБНОВИТЬ

Вы сказали:

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

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

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

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

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

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

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

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

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

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

Когда вы вызываете 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);
 }
}

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

Простой ответ будет: "Убийца не оставляет имени карты";)

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

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

Вы можете попытаться увеличить значение executeTimeout для конфигурации \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(); вместо использования потоков.

Использовать AsyncTasks для достижения вашей продолжительной работы в asp.net

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

Как выглядит потребление памяти во время работы этого потока? Можете ли вы использовать профилировщик памяти, чтобы посмотреть, не вышло ли оно из-под контроля? Можете ли вы добавить запись во внутренних циклах? Если у вас есть рекурсивный метод, добавьте счетчик и сгенерируйте исключение, если оно повторяется невозможное количество раз. Используете ли вы большие объекты, которые могут вызывать фрагментацию кучи больших объектов (приводит к ошибкам из-за недостатка памяти, даже если вы не работаете с ней)

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

Попробуйте использовать событие UnhandledException домена приложения: http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx

он может дать вам некоторую информацию, если вы пропустите некоторые исключения

Другие вопросы по тегам