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

Delphi 11 Android中MessageDialog线程导致ProgressBar不显示的解决方法

解决MessageDialog后ProgressBar不更新的问题

问题根源

TDialogService.MessageDialog 是异步执行的,其回调的匿名方法运行在非主线程中。而Delphi的UI控件(包括ProgressBar)必须在主线程中更新,直接在回调里修改UI属性会因为线程上下文不对而无法生效。另外你代码里还存在一个小错误:回调参数是AResult,但你写的是Result,这会导致判断逻辑失效。

修复方案

使用TThread.Synchronize将UI更新代码强制切换到主线程执行,同时修正参数名错误:

TDialogService.MessageDialog('Question?', System.UITypes.TMsgDlgType.mtInformation,
[System.UITypes.TMsgDlgBtn.mbYes, System.UITypes.TMsgDlgBtn.mbNo],
System.UITypes.TMsgDlgBtn.mbNo, 0,

procedure(const AResult: TModalResult)
begin
  if AResult = mrNo then
    Exit
  else begin
    // 将UI操作同步到主线程
    TThread.Synchronize(nil, procedure
    begin
      ProgressBar1.Visible := True;
      ProgressBar1.Value := i;
    end);

    // 注意:如果后续有耗时操作,必须放到单独线程中执行
    // 否则会阻塞主线程,导致ProgressBar仍然无法实时更新
    // 示例:用后台线程处理耗时任务并更新进度
    TThread.CreateAnonymousThread(procedure
    var
      j: Integer;
    begin
      for j := 0 to 100 do
      begin
        // 用Queue异步更新UI(比Synchronize更轻量,适合频繁更新)
        TThread.Queue(nil, procedure
        begin
          ProgressBar1.Value := j;
        end);
        Sleep(50); // 模拟耗时操作
      end;
    end).Start;
  end;
end);

关于定时器方案失效的说明

你之前尝试的定时器方案没生效,大概率是因为:

  • 定时器本身运行在主线程,但如果你的耗时操作仍然阻塞了主线程,定时器事件无法被触发
  • 外部变量的读写没有做线程同步,导致主线程无法正确获取最新值

相比定时器,直接用TThread.Synchronize/Queue是更直接、可靠的线程UI同步方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 17:52:44