首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >FMX.Graphics.TBitmap.Canvas可以安全地由线程创建吗?

FMX.Graphics.TBitmap.Canvas可以安全地由线程创建吗?
EN

Stack Overflow用户
提问于 2019-10-17 15:19:58
回答 2查看 607关注 0票数 2

我正在维护一个使用FMX.Graphics.TBitmap的Delphi10.2.3Isapi应用程序。多个线程正在创建自己的私有位图,绘制它,将二进制内容返回到webrequest处理程序,并释放位图。在此堆栈跟踪中发生调试访问冲突时:

代码语言:javascript
运行
复制
:760c4742 KERNELBASE.RaiseException + 0x62
System.DynArraySetLength(nil,$407163,16,$F)
System.DynArraySetLength($6113648,$5DDE84,1,$6B6FE78)
System.Generics.Collections.TListHelper.InternalSetCapacity(8514146)
System.Generics.Collections.TListHelper.InternalGrow(???)
System.Generics.Collections.TListHelper.InternalGrowCheck(???)
System.Generics.Collections.TListHelper.InternalAddManaged((no value))
System.Messaging.TMessageManager.SubscribeToMessage(???,(FMX.Canvas.D2D.TCanvasD2D.ContextLostHandler,$6122F70))
FMX.Canvas.D2D.TCanvasD2D.CreateFromBitmap(???,SystemDefault)
FMX.Graphics.TBitmap.GetCanvas
Unit1.TWorker.Execute

我怀疑FMX框架代码中的这个代码不是线程安全:

代码语言:javascript
运行
复制
// FMX.Canvas.D2D.pas:
constructor TCanvasD2D.CreateFromBitmap(const ABitmap: TBitmap; const AQuality: TCanvasQuality);
begin
  inherited;
  FLastBrushTransform := TMatrix.Identity;
  CreateResources;
  FContextLostId := TMessageManager.DefaultManager.SubscribeToMessage(TContextLostMessage, ContextLostHandler);
end;

它正在调用singleton TMessageManager.DefaultManager,并在其内部字典中添加一个处理程序,而不需要任何锁定。看起来不太安全。根据文档,使用BeginScene和EndScene时可以在线程中使用FMX位图,这很好。但是实际上创建/销毁FMX画布似乎并不是线程安全,因为订阅/取消订阅是单例默认的MessageManager?这个假设正确吗?

奇怪的是,只有当任何代码被暂停并通过断点在调试器的某个地方恢复时,它才可能引发访问冲突。当程序从未被断点暂停时,它将无问题地运行。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-23 08:56:04

我向您确认,FMX.Graphics.TBitmap.Canvas中的代码不是线程安全。请看一下,例如,您将看到它侦听消息,消息传递不是线程安全

代码语言:javascript
运行
复制
constructor TD2DBitmapHandle.Create(const AWidth, AHeight: Integer; const AAccess: TMapAccess);
begin
  inherited Create;
  FWidth := AWidth;
  FHeight := AHeight;
  FAccess := AAccess;
  FContextLostId := TMessageManager.DefaultManager.SubscribeToMessage(TContextLostMessage, ContextLostHandler);
end;
票数 0
EN

Stack Overflow用户

发布于 2019-10-28 13:32:42

如果您查看tcontext3d的代码,您将看到它使用密集的全局变量,因此不能是多线程!例如,在执行Tcontext3d时使用bitmap.canvas.beginscene

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58435930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档