【问题标题】:How do you handle errors in error handlers in VB6?您如何处理 VB6 中的错误处理程序中的错误?
【发布时间】:2009-02-11 11:25:16
【问题描述】:

我在我的 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 添加错误处理程序也有同样的问题。

确保原始错误仍然得到处理/记录的最佳方法是什么?

编辑:另外一个问题是我还想将错误通知用户。有时重要的是,清理发生得很快,我不希望消息框长时间阻塞应用程序并在用户确认错误后进行清理。

【问题讨论】:

    标签: vb6 error-handling


    【解决方案1】:

    首先,从 Err 对象中读取您需要的所有信息,即编号、描述等,然后清除错误并执行您想要的操作。

    更改通知用户使用缓存值的方式,而不是使用 Err 对象本身。

    【讨论】:

      【解决方案2】:

      从您的示例中,您正在正确地进行清理。您的 HandleError 应该只记录错误而不执行任何 UI。 UI 在表单级别处理。

      发生错误时你需要做的是

      1. 清理
      2. 记录错误
      3. 通过 Err.Raise 再次引发错误

      这将在调用堆栈向上到达调用原始代码的事件。那么序列就会变成

      1. 清理
      2. 记录错误
      3. 显示错误通知对话框

      请注意,您的错误记录可以是智能的,因为相同错误的后续日志可以添加到记录的调用堆栈中。

      您要确保每个事件都有一个错误处理程序。不是每个程序都需要一个,但绝对是每个事件。事件中未处理的错误将导致 VB6 应用程序意外关闭。

      【讨论】:

      • 虽然这并不能完全帮助您的建议产生了奇迹!我现在有一个更加复杂和强大的错误处理,包括(伪)堆栈跟踪。 (您没有提到缓存 Err 对象,这是我最初问题的解决方案,因此我接受了 Patricks 的回答)
      【解决方案3】:

      如果我可以在一个地方处理所有错误,我通常会放入这样的结构中:

      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
      

      如果我需要多个错误处理程序,我会非常努力地重组我的代码以使其不再是这种情况,但如果绝对必要,我会编写一个自定义处理程序;我的模板只是一个指南。

      【讨论】:

        【解决方案4】:

        首先记录您的错误。然后执行 On Error Resume Next。将您的清理封装在具有自己的错误处理的方法中。这应该是您最好的选择。

        【讨论】:

        • 谢谢。不幸的是,这并不总是对我有帮助。我已经为我的问题添加了解释。
        【解决方案5】:

        我真的不喜欢错误处理程序。我就是这样做的;

        • 创建一个 Error 类或模块,其中包含内置的所有属性,以及从 err-object 填充这些属性的 CopyError 方法。
        • 注意可能出现的错误:

        .

        ' 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
        

        【讨论】:

        • 一个小改进:您可以在 Error 类中将 Err.Raise... 行替换为 Raise 方法,该方法执行相同的操作,输入相同的内容。
        猜你喜欢
        • 1970-01-01
        • 2016-08-18
        • 1970-01-01
        • 1970-01-01
        • 2015-03-29
        • 1970-01-01
        • 1970-01-01
        • 2012-06-06
        • 1970-01-01
        相关资源
        最近更新 更多