【问题标题】:How to handle TIdHTTP fatal network errors without interrupting thread's execution?如何在不中断线程执行的情况下处理 TIdHTTP 致命网络错误?
【发布时间】:2014-06-11 16:43:36
【问题描述】:

我想详细说明如何正确处理由 TThread 的 Execute 过程中的 TIdHTTP 引发的致命网络异常。

我的应用在Execute 过程中运行while..do 循环。每个循环都会调用TIdHTTP.Get()。异常在循环级别处理。还有on E: Exception do的上层处理程序(Execute的级别)。

该场景假定在活动网络操作期间发生致命网络错误(即适配器中断、“对等方重置连接”等)。

10 个线程被序列化以从循环内部发出TIdHTTP.Get() 请求。当家庭路由器意外挂起时,该应用程序正在笔记本电脑上运行。 #10054 来了。假设网络在 10 分钟内返回。我想确保在网络突然死亡的情况下,每个线程都以某种方式:

  1. 检测到(嗯,这是最简单的)
  2. 等待网络恢复。
  3. 确保网络正常。
  4. 重新建立连接并恢复所有网络引擎盖。
  5. 继续循环。

期望的结果是保持线程正常运行,并在临时网络问题中幸存下来。线程必须定期检查网络是否恢复。如果是,异常处理程序必须恢复所有网络引擎调用线程的RestoreNetworkConnection,然后继续循环。

我绝对不想要的是停止线程的执行。

问题

  1. 我应该拦截哪些事件/异常来处理致命的网络错误?
  2. Execute 中的何处放置异常处理程序?
  3. 什么是重新建立连接回到正常状态的正确方法?

【问题讨论】:

  • 您实际上在这篇文章中提出了 6 个问题,因为 TIdHTTPTADOConnection 需要不同的方式来处理和恢复错误。这对于一篇文章来说已经足够了......
  • @TLama 哦,那是真的......谢谢你提到这一点。您是否建议发布两篇单独的帖子,一篇用于 TIdHTTP,另一篇用于 TADOConnection?
  • 是的,请。但无论如何,我不认为你真的在寻找只处理网络故障。当这些组件工作时,可能会发生许多其他不好的事情。想想服务器返回的所有那些 4xx HTTP 错误,或者当 DBMS 发生错误时返回的所有异常......可以检测到两个组件的连接丢失,但这只是可能失败的一小部分。
  • @TLama(我做到了,谢谢!)实际上一切都很好。应用程序幸存EIdSocketErrorEIdReadTimeout 等。现在正确处理#10054 和其他“硬件错误”会让我非常高兴:)
  • @TLama。 “这与您的链接问题完全相同,唯一的区别是您将捕获的异常类别以及重新建立连接的细微差别。它肯定可以合并为一个关于处理一般网络的问题线程中的异常,然后是第二个单独的问题(链接回第一个问题)可以只询问差异,而不是发布两个包含 90% 相同内容的单独长问题。(这里真的不适合复制/粘贴长问题,更改几个短语,然后再次发布)

标签: multithreading delphi exception-handling indy


【解决方案1】:

最简单的方法是这样做:

procedure TMyThread.Execute;
var
  NetworkDown: Boolean;
begin
  NetworkDown := False;
  try
    while not Terminated do
    begin
      // wait for a successful HTTP response...
      repeat
        if Terminated then Exit;
        try
          IdHTTP.Get(...);
          Break;
        except
          on E: EIdHTTPProtocolException do begin
            // process HTTP error as needed...
          end;
          on E: EIdSocketError do begin
            NetworkDown := True;
            // process socket error as needed...
          end;
          on E: Exception do begin
            // process any other error as needed...
            raise;
          end;
        end;
        Sleep(1000);
      until False;

      // got a response, check if network was previously down
      if NetworkDown then
      begin
        NetworkDown := False;
        RestoreNetworkConnection;
      end;

      // now process HTTP response as needed ...
    end;
  except
    on Exception do begin
      // process fatal error as needed ...
    end;
  end;
end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多