1

I am creating a simple game for Android using Delphi XE5. I have a few resources, PNGs and Jpegs, I wanted to show a loading screen while my program loads up all the resources.

But I found putting TBitmap.LoadFromFile, or TBitmap.LoadFromStream code inside a android thread, caused the App to quit immediately and return to Launcher, in debug mode Delphi don't even catch an exception. (The code works perfectly on Windows, and without thread on Android)

I had to open logcat to see what went on, I saw something like "Error creating drawing context".

My question is there a way to make a loading screen for Android using Delphi XE5? So that a progress screen shows while images gets loaded in memory.


I created test project just to isolate the problem, here are the result. LoadFromFile is Thread 1. The log suggests thread actually ran, but Exceptions were raised afterwards???

Logcat screenshot: Logcat Result Source code: http://www.pockhero.com/wp-content/uploads/2013/10/threadtest1.7z

4

2 回答 2

4

这显然是一个应该在下一次更新中修复的错误。要将修复应用于您的代码,请声明此过程:

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;

并将其分配给 System.Classes 中的 EndThreadProc:

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

通过此修复,您可以设置,例如,您的线程

FreeOnTerminate := true;

然后像这样的代码将不再使应用程序崩溃:

TYourThread.Create(something, somethingelse).Start;

我必须感谢 Antonio Tortosa 在 Embarcadero 论坛上发布此解决方案。

于 2014-01-23T20:15:27.147 回答
1

经过大量测试和同事的帮助,我和我的同事解决了这个问题。解决方案是不终止线程并保持线程运行。

我知道这有点奇怪。我试图关闭 FreeOnTerminate,但它只控制线程对象,而不是实际的线程。似乎同步调用未同步。我不知道位图何时何地被实际使用或复制。可能在某个地方还有另一个 GUI 线程,因为 Delphi 编译的 Android lib 代码无论如何都不会在主线程中运行。

这是工作代码。

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;
于 2013-10-22T03:21:49.190 回答