System.Threading.ThreadAbortException запускается в новом потоке

В настоящее время я работаю в .net С# 4.0 и столкнулся с проблемой, связанной с написанным мной кодом, который вызывает у меня некоторые головные боли.

Я использую класс System.Threading.Tasks.TaskFactory в сочетании с System.Threading.Tasks.TaskScheduler для запуска нового потока в моем консольном приложении, где функция потока заключается в проверке того, добавлен ли элемент в очередь. Когда элемент добавляется в очередь, он обрабатывает его.

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

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

[System.Threading.ThreadAbortException] = {Невозможно оценить выражение, так как код оптимизирован или собственный фрейм находится поверх стека вызовов.}

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

В поисках решения в Интернете я обнаружил, что это проблема, возникающая при выполнении response.redirect, но я не делаю этого в своем коде. Если я попытаюсь выполнить отладку, не будет согласованности в отношении того, где возникает эта ошибка. Ниже приведен код, который я использую для создания фабрики и запуска нового потока:

    this.taskFactory = new TaskFactory(TaskScheduler.Current);
    this.taskFactory.StartNew(this.DequeueMessage, state, TaskCreationOptions.LongRunning);

Есть ли у кого-нибудь какие-либо указания относительно того, почему я могу получить эту ошибку, и какие-либо советы относительно того, как ее можно исправить?


person amateur    schedule 17.07.2012    source источник
comment
Вы создаете задачи в веб-приложении? Если это так, вы, вероятно, видите, что AppDomain перерабатывается. Решение состоит в том, чтобы переместить ваши фоновые потоки в службу Windows.   -  person Nick Butler    schedule 17.07.2012
comment
Я вижу это поведение в простом интеграционном тесте, который я запускаю в Visual Studio. Также см. такое же поведение, когда я запускаю тот же код в консольном приложении.   -  person amateur    schedule 17.07.2012


Ответы (1)


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

person Peter Ritchie    schedule 17.07.2012
comment
Я вызываю этот код через интеграционный тест, написанный с помощью среды тестирования Microsoft Visual Studio. Меня только что осенило, что когда я запускаю тест, он завершается до того, как код полностью выполнится, следовательно, Thread.Abort. Возможно ли это? - person amateur; 17.07.2012
comment
@amateur Да, именно это и происходит. Процесс тестирования существует до завершения фонового потока. В вашем тесте вам нужно дождаться завершения фонового потока, прежде чем выйти из теста. Вы можете сделать это с помощью Task.Wait() (StartNew возвращает объект Task) - person Peter Ritchie; 17.07.2012
comment
Ах, не могу поверить, что до меня только сейчас дошло! Именно ваш ответ заставил меня задуматься! Когда я вызываю метод Wait для возвращаемого объекта Task, кажется, что задача переходит в состояние, в котором она ничего не делает, не обрабатывается, просто бездействует. Любая идея, почему это может быть так? - person amateur; 17.07.2012
comment
@amateur Подождите, это довольно просто. Если задача уже запущена, Wait просто ждет завершения задачи (т. е. вашего делегата). Если она еще не запущена, Wait вызывает выполнение задачи, а затем ждет ее завершения. В Task.Wait нет ничего, что могло бы повлиять на то, будет ли ваш делегат бездействовать или нет. - person Peter Ritchie; 17.07.2012