XE5 Android TBitmap.LoadFromStream fail inside a thread

那年仲夏 提交于 2019-12-01 12:24:12

This apparently is a bug that is supposed to be fixed in the next update. To apply the fix to your code, declare this procedure:

uses
  Androidapi.NativeActivity,
  Posix.Pthread;


procedure MyEndThreadProc(ExitCode:Integer);
var
  PActivity: PANativeActivity;
begin
    PActivity := PANativeActivity(System.DelphiActivity);
    PActivity^.vm^.DetachCurrentThread(PActivity^.vm);
    pthread_exit(ExitCode);
end;

and assign it to the EndThreadProc from System.Classes:

procedure TForm1.FormCreate(Sender: TObject);
begin
  EndThreadProc := MyEndThreadProc;
end;

With this fix you can set, for example, your thread with

FreeOnTerminate := true;

and then a code like this won't crash the application anymore:

TYourThread.Create(something, somethingelse).Start;

I have to give credit to Antonio Tortosa for posting this solution in Embarcadero forums.

After a lots of testing and colleague's help, my colleague and I solved the problem. The solution is not to terminate the thread and keep the thread running.

I know this is a bit odd. I tried to turn FreeOnTerminate off, but it only control the thread object, not the actually thread. It appears as if syncrhonized call is not syncrhonized. I have no idea when and where the bitmap is actually being used or copied. Possiblly there is another GUI thread somewhere, since Delphi compiled Android lib code don't run in the main thread anyway.

Here is working code.

procedure TBitmapThread.Execute;
begin
  inherited;
  BeforeExecute;
  try
    fBitmap := TBitmap.CreateFromFile(TPath.Combine(TPath.GetDocumentsPath, 'koala.jpg'));
    // Sleep(2000);
    Synchronize(UpdateImage);
    // Keep the thread running
    while not Terminated do
    begin
      Sleep(100);
    end;
    fBitmap.Free;
  except
    on E:Exception do
    begin
      Log.d('TestThread Exception: ' + E.message);
    end;
  end;
  AfterExecute;
end;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!