我有一个我的应用程序的形式,可以有多达1000个可视组件,其中我使用位图的Canvas绘制每一个,并保存每个组件的位图(一种双缓冲),因为每个操作需要20毫秒。
我正在使用线程绘制位图并使用此位图向MainThread发送通知,以刷新可视组件,UI。
理论上,它必须有一个流体形式的开口,当它们的位图涂在螺纹中时显示组件,但实际上它不是流动的。我决定看看delphi的TCanvas,我发现了一些令人震惊的事情:
class var // <<<<<<<<<<<<<<<<<<<<<<<<<<<< class var
FLock: TObject;
function TCanvas.BeginScene(AClipRects: PClipRects = nil; AContextHandle: THandle = 0): Boolean;
begin
Lock;
...
end;
procedure TCanvas.EndScene;
begin
...
Unlock;
end;
class procedure TCanvas.Lock;
begin
TMonitor.Enter(FLock);
end;
class procedure TCanvas.Unlock;
begin
TMonitor.Exit(FLock);
end;
这绝对不对。为什么embarcadero无法在不同的线程中同时使用TCanvas?创建10个线程来进行位图绘制是没有用的,因为一次只能处理1个...
我知道很多人会建议我使用本机类,Android中的JCanvas和iOS中的CGContextRef,但我想要一个TCanvas的解决方案,因为它的工作是成为绘制所有平台功能的包装器,并且很容易使用。
============= @EDIT =============
我在FMX.Graphics单元中更改了TCanvas的锁定和解锁,以使用本地而不是全局监视器,以及FMX.Types3D单元中TContext3D的BeginScene和EndScene。 我对这一变化非常担心,但显然应用程序正常工作,最大的工作是重新编译整个FMX。
答案 0 :(得分:1)
Tbitmap并不是真正的多线程。它在Delphi东京被制作为多线程但设计非常糟糕(当你在后台线程中使用Tbitmap时,它们仍然是很多bug,例如Tbitmap仍然使用根本不是多线程的消息通知,因此可能导致随机例外)。在tokyo中做得不错的是使OpenGL上下文多线程(在android / ios下),并且工作得很好(但不是仍然绑定到Messaging的TTexture,但你可以轻松更新ttexture的源代码来纠正它(您可以查看Alcinoe的源代码以了解如何操作)。
您希望实现的唯一解决方法是:
是的,我知道这很痛苦!