Частично отказывающее приложение? Как я могу поймать неуловимые исключения?

Мне записали программу в C#, работая на устройстве Windows CE (на Компактной Платформе). Это обрабатывает минимальные пользовательские действия (нажатия кнопок), использует коммуникация TCP/IP и последовательный порт.

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

Так как у меня заканчиваются идеи, вопрос: какая ошибка или исключение или действие ОС или аппаратное неправильное функционирование могут вызвать такое поведение?

Проблема была замечена на различных устройствах того же типа, таким образом, это не должна быть аппаратная ошибка. (Или все мои аппаратные средства имеют ту же ошибку.) Исключения обработаны, таким образом, это не должно быть исключение. Необработанные исключения обрабатываются также, таким образом, это не должно быть необработанное исключение также. (Мое предположение - то, что это вызывается a StackoverflowException потому что я не знаю никакие другие исключения, которые не могут быть пойманы, но нет рекурсии в коде, по крайней мере, не охотно, таким образом, это не должна быть возможность также.)

9
задан RJFalconer 12 August 2014 в 11:25
поделиться

3 ответа

Некоторые исключения невозможно поймать, и они различаются в разных версиях .NET. А некоторые исключения могут быть пойманы и записаны в журнал, но не могут быть восстановлены (исключения памяти). Однако их можно отлаживать (они называются исключениями первого шанса, первый шанс всегда для отладчика, второй - для кода, спасибо JeroenH за указание на это). Вот пост на CodeProject, который объясняет этот принцип.

Что вы должны сделать, так это выбрать в Visual Studio несколько исключений-кандидатов, которые, как вы подозреваете, могут возникнуть, и подключить отладчик к запущенному экземпляру.

Наличие неуправляемых ресурсов, как у вас (последовательный порт), означает, что у вас могут быть неуправляемые утечки (неправильное использование IDisposable + using) и неуправляемые исключения. Эти исключения могут быть пойманы только с помощью пустого catch (т.е. без указания даже Exception, который является не родителем неуправляемых исключений) в блоке try/catch.

PS: некоторые неопределенные действия могут происходить, когда исключения поднимаются в блоках finally или в финализаторах/деструкторах. Кроме того, не многие исключения распространяются через границы потоков и завершают все потоки.

Редактировать

Чтобы немного прояснить ситуацию, есть несколько исключений, которые CLR (и его спецификация) определяет как нефиксируемые. По сути, это все исключения, которые пересекают границы потоков. Эти асинхронные исключения, возникающие внутри блокировки, приводят к повреждению состояния. Наиболее известны OutOfMemoryException, ThreadAbortException и StackOverflowException. Когда OutOfMemoryException или StackOverflowException возникает в синхронном коде, маловероятно, что вы сможете исправить состояние, и CLR завершит ваше приложение.

Кроме того, существуют ExecutionEngineException и BadImageFormatException, которые не должны возникать в проверяемом коде и не должны быть пойманы. Такие исключения, как TypeLoadException и MissingMemberException, иногда можно поймать, а иногда нет (если отсутствует связанная сборка, их будет трудно поймать, и вы не должны этого делать, но если вы используете отражение, вы должны их поймать).

Короче говоря: исключения должны быть пойманы в том потоке, в котором они происходят. Вы не сможете поймать исключения, если они произойдут в другом потоке, потому что они не распространяются (за исключением ThreadAbortException). Ваше приложение остается живым после исключения (по крайней мере, вы так думаете), поэтому логично предположить, что исключение не происходит в потоке, в котором вы пытаетесь его поймать. Используя окно Debug > Exceptions, вы можете выбрать любое исключение и прервать код, когда оно происходит.

Примечание по исключениям

Дополнительное замечание по управляемым и неуправляемым исключениям. Вы не можете поймать неуправляемое исключение с помощью catch (Exception e), потому что неуправляемое исключение не наследуется от Exception. Вместо этого используйте пустой catch, который перехватит для вас любое неуправляемое исключение. Оберните это вокруг вашего приложения и методов точки входа потока, и вы сможете отлавливать большинство отлавливаемых исключений.

10
ответ дан 4 December 2019 в 13:44
поделиться

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

Вы вызываете или делаете небезопасные вызовы? Если вы вызываете API и вызываете что-то вроде выхода за пределы буфера или повреждения стека, вы увидите подобное поведение (хотя часто вы получите диалог ОС с жалобой).

Отследить это часто бывает непросто. Это устройство CE - есть ли у него порт отладки (обычно это последовательный порт)? Вполне вероятно, что исключение сбросит сообщение туда, так что если у вас есть доступ к такому порту, это хорошая отправная точка. Если у вас есть KITL, запуск ОС в режиме отладки во время работы приложения также может отловить происходящее.

3
ответ дан 4 December 2019 в 13:44
поделиться

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

Если бы у вас была исключение StackOverflowException, ваш процесс был бы полностью убит Windows, так что это не так.

2
ответ дан 4 December 2019 в 13:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: