PNG解码在Android下不是线程安全的吗?

时间:2018-09-04 14:48:46

标签: android multithreading delphi png firemonkey

使用Delphi 10.2.3:

我正在编写代码,一次又一次地重复解码多个线程中的同一组PNG图像。

一旦线程执行完毕,它将使用FMX TBitmap组件的“ LoadFromStream”方法对加载到TMemoryStream中(线程内)的PNG文件进行解码。

在Windows下运行,没有问题。

在Android上运行时,我遇到多个异常,它似乎只是在某些线程上随机触发:
1.异常“无法激活当前上下文”
2. EReadError“流错误”

如果我捕获到异常并将流保存到文件中,则PNG有效。

如果我同步解码“ Bitmap.LoadFromStream(MemoryStream)”功能,一切正常。

如果答案是使用本机库进行PNG解码不是线程安全的,那么是否有替代解决方案支持Android下的多线程PNG解码?

示例代码:

procedure TImageDecodeThread.Execute;
var
  memStream  : TMemoryStream;
  dlBitmap   : TBitmap;
Begin
  memStream := TMemoryStream.Create;
  Try
    memStream.LoadFromFile('image'+ThreadName+'.png');
  Except
    on E : Exception do
    Begin
      DebugEntry('memstream:'+E.ClassName+', "'+E.Message+'", Size='+IntToStr(memStream.Size));
    End;
  End;
  memStream.Position := 0;

  dlBitmap := TBitmap.Create;
  Try
    dlBitmap.LoadFromStream(memStream);
  Except
    on E : Exception do
    Begin
      DebugEntry('decode'+E.ClassName+', "'+E.Message+'", Size='+IntToStr(memStream.Size));
      memStream.Position := 0;
      memStream.SaveToFile(ThreadName+'exception'.png');
    End
  End;
  memStream.Free;
  dlBitmap.Free;
End;

更新
我试图将TBitmap的LoadFromStream方法包装在关键部分中,但它仍然引发“无法激活当前上下文”异常。

1 个答案:

答案 0 :(得分:-1)

PNG图像可以在Android下的后台线程中工作,但Tbitmap可能不是;)Embarcedero说从delphi tokyo Tbitmap可以在后台线程中工作,但实际上这是错误的(或者最好说完全是越野车)!例如,当您创建Ttexture时,控件将注册一些消息以进行侦听(例如丢失上下文),但是可以发送消息事件,并且只能从主线程中读取消息!因此它们是一个问题,通常是由于随机访问导致访问冲突或崩溃。我记下了一些必须纠正的纹理,以使Tbitmap在https://github.com/Zeus64/alcinoe

中的后台线程中完全起作用

还请注意,您说它在Windows下运行,但这也是错误的!这取决于您的视频驱动程序和DirectX的版本。在某些Windows上,这绝对是行不通的,我还报告了embarcadero质量门户网站下的许多此类错误

作为结论:Tbitmap现在不能在后台线程中使用...