【问题标题】:Try/Except/Finally not working properly in Delphi XETry/Except/Finally 在 Delphi XE 中无法正常工作
【发布时间】:2014-05-04 03:18:37
【问题描述】:

我在使用 Delphi XE 时遇到了一个有趣的问题,我在其中创建了一个 try/except/finally 语句,当应用程序生成异常时,从不调用 except 块直接跳转到 finally 块,我尝试了一些类似 invert 的方法将 try/except/finally 改为 try/finally/except,尝试将 try 块更改到不同的位置,清理代码并重新编译,以防出现 Delphi 问题,但注意似乎有效。

我在这里尝试完成的是向用户显示对话框消息,并在清理代码以防崩溃。

procedure CallbackExport(Sender: TObject);
var
  SaveDlg: TSaveDialog;
  FileName: string;
begin
  SaveDlg := TSaveDialog.Create (nil);
  try
    try
      SaveDlg.Title := 'Export';
      SaveDlg.InitialDir := GetSystemPath(CSIDL_DESKTOP);
      SaveDlg.Options := [ofOverwritePrompt, ofEnableSizing];

      case (Sender as TMenuItem).Tag of
        cnExcel: begin
          SaveDlg.Filter := 'Excel File (*.xls)|*.xls';
        end;
        cnHtml: begin
          SaveDlg.Filter := 'HTML File (*.html)|*.html';
        end;
        cnTxt: begin
          SaveDlg.Filter := 'Text File (*.txt)|*.txt';
        end;
        cnCsv: begin
          SaveDlg.Filter := 'Comma Seperated File (*.csv)';
        end;
        cnXml: begin
          SaveDlg.Filter := 'XML file (*.xml)|*.xml';
        end;
      end;
      if not SaveDlg.Execute(self.Handle) then
        Exit;
      FileName := SaveDlg.FileName;

      case (Sender as TMenuItem).Tag of
        cnExcel: begin
          ExportGridToExcel(FileName, tvdGrid);
        end;
        cnHtml: begin
          ExportGridToHTML(FileName, tvdGrid);
        end;
        cnTxt: begin
          ExportGridToText(FileName, tvdGrid);
        end;
        cnCsv: begin
          ExportGridToText(FileName, tvdGrid, true, true, ',', '', '', 'CSV');
        end;
        cnXml: begin
          ExportGridToXML(FileName, tvdGrid);
        end;
      end;
    except
      on e: exception do
      begin
        ShowMessage('An error occurred while saving the file ' + FileName + #13#10 + 'With a message: ' + E.Message);
        StvdAudit.tvdAudit('Error saving file, reason: ' + E.Message);
      end;
    end;
  finally
    SaveDlg.Free;
  end;
end

【问题讨论】:

  • 这段代码看起来应该可以工作。您能否提供一个我们可以实际编译和测试的可重现示例?
  • 您如何知道正在生成异常?尝试显式地引发异常,看看会发生什么。放“引发异常。创建('这是一个异常');”第二次尝试后。
  • 我同意。如图所示,这段代码中很少会引发异常。
  • 我的猜测是 ExportGrid 函数可能正在处理/处理异常(try..except 在其中)。由于对这些函数的调用是 try..finally 块中的最后一个可执行行,因此它会在跳转到 finally 语句时出现。为了确认这一点,您可以在您的 except 子句之前添加一个 ShowMessage 并查看在 IDE 向您显示异常后是否收到该消息。如果是这种情况,您将不必处理该函数内部的异常或在 except 块上重新引发它(只是raise;)。不知道有没有说清楚……
  • 我从未使用过 DevExpress,所以我无法断言任何东西,但我仍然猜测 ExportGrid 函数正在处理异常。我建议您设置一个断点并一直深入到 DevExpress 源代码(函数上的 [F7])中,以跟踪异常发生的位置以及处理的位置。您应该有源代码,但可能不在库路径中(这样可以避免重新编译,从而节省时间)。但是当调试器请求 .pas 文件时,找到它并在调试器上选择(通常组件在其树中带有 source 目录)。

标签: delphi exception-handling try-catch delphi-xe


【解决方案1】:

您的异常处理程序正在吞噬异常,请尝试重新引发:

on e: exception do 
begin
  StvdAudit.tvdAudit('Error saving file, reason: ' + E.Message);
  raise exception.create('An error occurred while saving the file ' + FileName + #13#10 +       'With a message: ' + E.Message);
end;

【讨论】:

    【解决方案2】:

    Export(smth) 函数是否驻留在单独的 DLL 中?那么你的应用程序的Exception 类与外部DLL 的Exception 类是不一样的。

    【讨论】:

      【解决方案3】:

      如果在 try/except 中引发异常,并且未由调用堆栈下方的代码处理,则异常处理程序将捕获该异常。

      您声称ExportGridToXXX 引发了一个异常,该异常未被您的代码中的异常处理程序捕获。但这种说法不可能是真的。要么没有引发异常,要么ExportGridToXXX 已经处理了异常。

      关于异常处理这个更一般的主题,一般策略应该是尽可能不处理它们。您应该只在需要停止异常传播并且需要在代码中此时处理异常的情况下处理它们。通常,特别是在 UI 程序中,您只需让异常由顶级异常处理程序处理即可。

      除此之外,您的代码会吞下所有异常,无论其类型如何。这是不好的做法。假设您确实想要处理由ExportGridToXXX 引发的异常,您应该只处理预期的异常类。例如,您可能会遇到 EAccessViolation ,您的应用程序的政策将终止该 EAccessViolation。但是,由于您吞下了它,并在用于捕获共享违规的同一处理程序中处理它,因此您无法应用该策略。在处理异常时始终保持敏锐的洞察力。

      【讨论】:

        猜你喜欢
        • 2018-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-25
        • 2013-04-15
        相关资源
        最近更新 更多