2009-02-11 3 views
4

я часто сталкиваюсь с этой ситуацией в своих приложениях VB6Как вы обрабатываете ошибки в обработчиках ошибок в VB6?

Private Sub DoSomething 

    On Error Goto err1 

    Call ProcessLargeBatch1 
    Call ProcessLargeBatch2 
    '... more ...' 

    Exit Sub 

err1: 
    Call Cleanup 'Specific for DoSomething' 
    Call HandleError 'General error handling: Logging, message box, ...' 

End Sub 

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

Что мне делать в этом случае? Я добавлю On Error Resume Next в обработчик ошибок, но удалит существующий объект Err. Аналогичная проблема возникает при добавлении обработчика ошибок в Cleanup.

Каков наилучший способ гарантировать, что исходные ошибки все еще обрабатываются/регистрируются?

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

ответ

4

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

Измените способ информирования пользователя о том, как использовать кешированные значения, а не использовать сам объект Err.

1

Запишите сначала свою ошибку. Затем выполните следующее. Сделайте свою очистку инкапсулированной в методы, которые имеют собственную обработку ошибок. Это должна быть ваша ставка.

+0

спасибо. К сожалению, это не всегда помогает мне. Я добавил объяснение к моему вопросу. –

0

Мне действительно не нравятся обработчики ошибок. Вот что я делаю;

  • Создайте класс ошибок или модуль, содержащий все свойства, которые встроенный в них содержит, а также метод CopyError, который заполняет эти свойства из err-объекта.
  • Часы для ошибок, где они могут появиться:

.

' lots of code that will probably work 
On Error Resume Next 
Open "c:\filethatdoesntexist.txt" For Input As #1 
Error.CopyError 
On Error Goto 0 
Select Case Error.Number 
    Case 53'File doesn't exist 
     ' handle that error here 
    Case 0 
     ' no error 
    Case Else 
     ' Just throw the error on 
     Err.Raise Error.Number, Error.Description, ... 
End Select 
' more code that will probably work 
+0

Небольшое улучшение: вы можете заменить строку 'Err.Raise ...' методом 'Raise' в вашем классе' Error', который делает то же самое, с тем же набором символов. –

2

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

Public Sub SubThatShouldHandleErrors() 
Const ROUTINE_NAME = "SubThatShouldHandleErrors" 
On Error Goto Catch 

    ' "normal" processing here... 

Finally: 
    ' non-error case falls through to here 
    ' perform clean-up that must happen even when an error occurred 
    On Error Goto 0 ' reset: not really needed any more, but it makes me feel more comfortable 
    Exit Sub 

Catch: 
    ' Error handling here, I may have logging that uses ROUTINE_NAME 
    Resume Finally 

End Sub 

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

3

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

Что вам нужно, когда происходит ошибка

  1. Clean Up
  2. Вход Ошибка
  3. Поднимите ошибки снова через Err.Raise

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

  1. Clean Up
  2. Входа Ошибка
  3. Выводит Уведомление об ошибке Dialog

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

Вы хотите удостовериться, что событие EVERY имеет обработчик ошибок. Не каждому процессу нужно одно, но определенно каждое событие. Необработанные ошибки в событии приведут к неожиданному завершению работы приложения VB6.

+0

Хотя это не совсем помогает вашему предложению, он творит чудеса! У меня теперь гораздо более сложная и надежная обработка ошибок, включая трассировку стека (псевдо). (Вы не упомянули кэширование объекта Err, который был решением моего первоначального вопроса, поэтому я принял ответ Patricks) –

+0

Рад помочь. –