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

使用Devart SSH组件时,如何获取结果后手动终止OmniThread线程?

解决方案

核心思路

  1. 保留OmniThread线程/取消令牌的引用,方便后续触发终止操作
  2. 在SSH Shell的数据接收事件中判断结果是否接收完成,一旦满足业务条件就触发线程终止
  3. 线程内部需响应终止信号,及时退出执行流程

具体实现步骤

1. 声明窗体变量

在主窗体私有字段中保存线程控制对象和取消令牌:

private
  FSSHWorkerControl: IOmniWorkerControl;
  FCancelToken: IOmniCancelToken;

2. 启动OmniThread线程

在触发逻辑(比如按钮点击)中启动线程,线程负责发送SSH命令并等待终止信号:

procedure TMainForm.btnRunCommandClick(Sender: TObject);
begin
  // 确保SSH连接已建立
  if not ScSSHClient.Connected then Exit;

  // 创建取消令牌,用于触发线程终止
  FCancelToken := CreateCancelToken;

  // 启动OmniThread任务
  FSSHWorkerControl := CreateTask(
    procedure(const task: IOmniTask)
    begin
      // SSH组件是VCL控件,必须在主线程发送命令
      TThread.Queue(nil,
        procedure
        begin
          ScSSHShell.SendCommand('show system status'); // 替换为你的目标命令
        end
      );

      // 线程阻塞,等待终止信号
      FCancelToken.WaitFor;
    end
  ).Run;
end;

3. 处理SSH Shell的数据接收事件

在TScSSHShell的OnDataReceived事件中,判断结果是否完整,触发线程终止:

procedure TMainForm.ScSSHShellDataReceived(Sender: TObject; const Data: string);
begin
  // 把收到的数据输出到界面(可选)
  MemoOutput.Lines.Add(Data);

  // 根据业务逻辑判断结果是否接收完成
  // 示例:假设设备返回结果以"COMMAND_FINISHED"作为结束标记
  if Pos('COMMAND_FINISHED', Data) > 0 then
  begin
    // 触发线程终止
    if Assigned(FCancelToken) then
    begin
      FCancelToken.Signal;
      FCancelToken := nil;
    end;

    // 释放线程引用
    if Assigned(FSSHWorkerControl) then
    begin
      FSSHWorkerControl := nil;
    end;
  end;
end;

4. 线程安全注意事项

  • Devart的SSH组件属于VCL控件,所有对组件的操作(如SendCommand)必须在主线程执行,因此用TThread.Queue包裹
  • 线程内部不要直接操作VCL界面元素,如需更新界面同样使用Queue或Synchronize

替代方案:检查线程Terminated属性

如果不需要使用取消令牌,也可以在线程循环中定期检查task.Terminated属性:

FSSHWorkerControl := CreateTask(
  procedure(const task: IOmniTask)
  begin
    TThread.Queue(nil,
      procedure
      begin
        ScSSHShell.SendCommand('show system status');
      end
    );

    // 循环等待终止信号
    while not task.Terminated do
    begin
      Sleep(100); // 短暂休眠降低CPU占用
    end;
  end
).Run;

// 数据接收事件中终止线程
procedure TMainForm.ScSSHShellDataReceived(Sender: TObject; const Data: string);
begin
  MemoOutput.Lines.Add(Data);
  if Pos('COMMAND_FINISHED', Data) > 0 then
  begin
    if Assigned(FSSHWorkerControl) then
    begin
      FSSHWorkerControl.Terminate;
      FSSHWorkerControl := nil;
    end;
  end;
end;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 12:10:50