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

Delphi FMX框架Canvas批量绘制提速:BeginScene/EndScene与多线程疑问

Delphi FMX Canvas绘制优化与BeginScene/EndScene详解

1. BeginScene/EndScene的核心作用与耗时

BeginScene和EndScene是FMX Canvas管理渲染上下文的成对方法:

  • BeginScene:锁定Canvas的渲染环境,初始化必要的渲染状态(比如绑定目标缓冲区、设置默认绘制参数),确保后续绘制指令能被正确缓存。
  • EndScene:解锁渲染上下文,将当前缓存的所有绘制指令一次性提交给GPU执行,完成后释放相关资源。

单次调用这对方法的耗时极低(通常是微秒级),但如果像你现在这样每绘制一个对象就调用一次,数千次累计下来的上下文切换、GPU提交开销会成为性能瓶颈——这部分开销远大于绘制单个矩形的耗时。

2. 最优调用方式:批量绘制

毫无疑问,**单次BeginScene后完成所有绘制操作,最后调用一次EndScene**是最高效的方式。你的现有代码每次绘制一个矩形就开启/关闭场景,完全浪费了批量绘制的性能优势。优化后的代码示例:

MyCanvas.BeginScene;
try
  // 统一设置绘制参数,避免重复设置
  MyCanvas.Stroke.Color := clablue;
  MyCanvas.Stroke.Kind := TBrushKind.Solid;

  // 批量绘制所有对象
  for var I := 0 to 9999 do
  begin
    // 此处获取或计算当前要绘制的MyRect
    MyCanvas.DrawRect(MyRect, 0, 0, AllCorners, 1);
  end;
finally
  // 确保无论是否出错,都能正确结束场景
  MyCanvas.EndScene;
end;

3. 多线程绘制的注意事项

FMX的Canvas不支持多线程同时操作同一个实例。BeginScene本身是线程不安全的,同一时间只能有一个线程持有Canvas的渲染锁,强行多线程绘制会导致渲染错乱、程序崩溃等问题。

如果想利用多线程提升绘制效率,正确的方案是:

  • 每个工作线程独立绘制到自己的离屏TBitmap.Canvas(离屏Canvas是线程安全的,只要每个线程用自己的实例)
  • 所有线程完成绘制后,在主线程中将所有离屏Bitmap的内容一次性绘制到主Canvas上(这个合并过程只需要一次BeginScene/EndScene)

关键结论

  • 频繁调用BeginScene/EndScene是性能杀手,务必批量处理所有绘制操作
  • 单次BeginScene/EndScene开销可忽略,但高频调用会累计大量不必要的开销
  • 同一Canvas无法多线程并行绘制,可采用离屏Canvas+主线程合并的方式实现多线程加速

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:41:07