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

如何在代码创建的Connection上使用OnInfoMessage事件实现进度条

数据库备份进度条实现:利用OnInfoMessage追踪STATS进度

你的思路完全可行——SQL Server执行BACKUP ... WITH STATS = 1时,每完成1%就会返回一条状态消息,通过Connection的OnInfoMessage事件可以捕获这些消息,进而同步更新UI进度条。以下是具体实现步骤和代码示例:

1. 修改备份线程类定义

添加自定义进度更新事件,同时新增OnInfoMessage的处理方法,用于解析进度并同步到主线程:

type
  // 自定义进度更新事件类型
  TProgressUpdateEvent = procedure(Sender: TObject; Progress: Integer) of object;

  TThreadBackUp = class(TThread)
  protected
    procedure Execute; override;
    // 处理Connection的信息消息
    procedure HandleInfoMessage(Sender: TObject; const Msg: string);
    // 同步进度到主线程
    procedure SyncProgressToUI(Progress: Integer);
  public
    DataSource : TMSDataSource;
    Connection : TMSConnection;
    Query : TMSQuery;
    DBName : string;
    BackUpFile : string;
    // 对外暴露的进度更新事件
    OnProgressUpdate: TProgressUpdateEvent;
    constructor Create(CreateSuspended: Boolean); override;
end;

2. 实现线程类的核心方法

constructor TThreadBackUp.Create(CreateSuspended: Boolean);
begin
  inherited;
  // 绑定Connection的信息消息事件
  if Assigned(Connection) then
    Connection.OnInfoMessage := HandleInfoMessage;
end;

procedure TThreadBackUp.HandleInfoMessage(Sender: TObject; const Msg: string);
var
  ProgressStr: string;
  Progress: Integer;
begin
  // 解析SQL Server返回的进度消息(示例为英文格式:"1 percent processed.")
  if Pos('percent processed', Msg) > 0 then
  begin
    ProgressStr := Copy(Msg, 1, Pos(' ', Msg) - 1);
    if TryStrToInt(ProgressStr, Progress) then
      SyncProgressToUI(Progress);
  end;
end;

procedure TThreadBackUp.SyncProgressToUI(Progress: Integer);
begin
  // 使用Queue而非Synchronize,避免阻塞备份线程
  Queue(procedure
        begin
          if Assigned(OnProgressUpdate) then
            OnProgressUpdate(Self, Progress);
        end);
end;

procedure TThreadBackUp.Execute();
begin
  // 确保Query关联当前线程的Connection
  Query.Connection := Connection;
  Query.SQL.Text := 'BACKUP DATABASE ' + DBName +
    ' TO DISK = ' + QuotedStr(BackUpFile) +
    ' WITH CHECKSUM, INIT, STATS = 1';

  Query.Execute;
end;

3. 主线程调用并订阅进度更新

在启动备份线程时,绑定进度更新事件,直接操作UI组件:

var
  CreateBackUp: TThreadBackUp;
begin
  CreateBackUp := TThreadBackUp.Create(True);
  CreateBackUp.FreeOnTerminate := True;
  try
    CreateBackUp.DataSource := MSDSChanges;
    CreateBackUp.Connection := MSConnLyubenAirport;
    CreateBackUp.Query := MSQChanges;
    CreateBackUp.DBName := CreateBackUp.Connection.Database;
    CreateBackUp.BackUpFile := odlgOpenBackUp.FileName;
    
    // 绑定进度更新事件,直接更新UI
    CreateBackUp.OnProgressUpdate := procedure(Sender: TObject; Progress: Integer)
                                     begin
                                       ProgressBar1.Position := Progress;
                                       Label1.Caption := Format('备份进度:%d%%', [Progress]);
                                       // 进度到100时可添加完成提示
                                       if Progress = 100 then
                                         ShowMessage('备份完成');
                                     end;
                                     
    CreateBackUp.Start;
  except on EConvertError do
    CreateBackUp.Free;
  end;
end;

注意事项

  • 若数据库是中文环境,STATS返回的消息格式会变为"已处理 1%",需要调整HandleInfoMessage中的解析逻辑(比如匹配'已处理'关键字)。
  • 若外部Connection已有绑定的OnInfoMessage事件,需先保存原有事件,备份完成后恢复,避免覆盖冲突。
  • 使用Queue同步UI操作,不会阻塞备份线程的执行,相比Synchronize更高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 07:41:35