You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从其他线程中止THTTPReqResp.Execute方法正在执行的HTTP请求

Delphi THTTPReqResp 主动中止HTTP请求解决方案

核心原理

THTTPReqResp底层基于WinINet API实现,本身没有暴露直接中止请求的方法,但可以通过主动关闭其内部使用的WinINet请求句柄,强制中断阻塞中的Execute调用。

实现步骤

  1. 引用WinINet单元,用于调用WinINet原生API
  2. 自定义工作线程类,增加私有变量存储WinINet请求句柄,并用临界区保护该句柄的多线程访问
  3. 绑定THTTPReqResp的OnBeforePost事件,在事件触发时获取当前请求的WinINet句柄存入线程变量
  4. 需要中止线程时,先设置线程终止标志,再通过InternetCloseHandle关闭存储的请求句柄,此时阻塞的Execute方法会抛出异常,即可中断执行流程

代码示例

uses
  System.SysUtils, System.Classes, System.SyncObjs, Soap.HTTPReqResp, WinINet;

type
  TWorkThread = class(TThread)
  private
    FReqHandle: HINTERNET;
    FCritical: TCriticalSection;
    procedure OnBeforePost(const Sender: TObject; const Request: HINTERNET);
  protected
    procedure Execute; override;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Stop;
  end;

constructor TWorkThread.Create;
begin
  inherited Create(True); // 创建挂起线程
  FCritical := TCriticalSection.Create;
  FReqHandle := 0;
end;

destructor TWorkThread.Destroy;
begin
  FCritical.Free;
  inherited;
end;

procedure TWorkThread.OnBeforePost(const Sender: TObject; const Request: HINTERNET);
begin
  FCritical.Enter;
  try
    FReqHandle := Request;
  finally
    FCritical.Leave;
  end;
end;

procedure TWorkThread.Execute;
var
  HTTPReqResp: THTTPReqResp;
  Request, Response: TStringStream;
begin
  HTTPReqResp := nil;
  Request  := nil;
  Response := nil;
  try
    HTTPReqResp := THTTPReqResp.Create(nil);
    HTTPReqResp.OnBeforePost := Self.OnBeforePost; // 绑定事件获取请求句柄

    HTTPReqResp.URL := 'some_url';
    HTTPReqResp.WebNodeOptions := [wnoSOAP12];
    HTTPReqResp.SendTimeout := 60000;
    HTTPReqResp.ConnectTimeout := 60000;
    HTTPReqResp.ReceiveTimeout := 60000;

    Request := TStringStream.Create('<Request_XML>test</Request_XML>', TEncoding.UTF8);
    Response := TStringStream.Create('', TEncoding.UTF8);

    try
      HTTPReqResp.Execute(Request, Response);
      // 正常处理返回逻辑
    except
      // 主动关闭句柄会触发异常,主动终止场景直接退出即可
      on E: Exception do
      begin
        if Terminated then Exit;
        // 非主动终止的其他异常按原有业务逻辑处理
      end;
    end;
  finally
    FCritical.Enter;
    try
      FReqHandle := 0; // 清空句柄标记
    finally
      FCritical.Leave;
    end;
    Response.Free;
    Request.Free;
    HTTPReqResp.Free;
  end;
end;

procedure TWorkThread.Stop;
begin
  Terminate; // 设置线程终止标志
  FCritical.Enter;
  try
    if FReqHandle <> 0 then
    begin
      InternetCloseHandle(FReqHandle); // 关闭请求句柄,中断Execute调用
      FReqHandle := 0;
    end;
  finally
    FCritical.Leave;
  end;
  WaitFor; // 等待线程安全退出
end;

注意事项

  • 句柄访问必须加临界区保护,避免多线程下同时操作句柄导致的内存访问错误
  • 主动关闭句柄触发的异常属于正常终止流程,无需当成业务错误处理
  • 禁止直接在主线程释放正在执行请求的THTTPReqResp实例,必须先调用Stop方法终止请求流程再释放线程资源

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 09:06:05