如何在代码创建的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
相关产品推荐
相关产品推荐

