XE5 Android TBitmap.LoadFromStream在线程内失败
我正在使用DelphiXe5为Android创建一个简单的游戏。我有一些资源,PNG和JPEG,我想在我的程序加载所有资源时显示一个加载屏幕 但我发现将TBitmap.LoadFromFile或TBitmap.LoadFromStream代码放入android线程中会导致应用程序立即退出并返回到启动器,处于调试模式,Delphi甚至不会捕获异常。(该代码在Windows上运行完美,在Android上没有线程) 我必须打开logcat来查看发生了什么,我看到了类似“创建绘图上下文时出错”的内容 我的问题是,有没有一种方法可以使用Delphi XE5为Android制作加载屏幕?这样,当图像加载到内存中时,会显示一个进度屏幕XE5 Android TBitmap.LoadFromStream在线程内失败,android,multithreading,delphi,delphi-xe5,Android,Multithreading,Delphi,Delphi Xe5,我正在使用DelphiXe5为Android创建一个简单的游戏。我有一些资源,PNG和JPEG,我想在我的程序加载所有资源时显示一个加载屏幕 但我发现将TBitmap.LoadFromFile或TBitmap.LoadFromStream代码放入android线程中会导致应用程序立即退出并返回到启动器,处于调试模式,Delphi甚至不会捕获异常。(该代码在Windows上运行完美,在Android上没有线程) 我必须打开logcat来查看发生了什么,我看到了类似“创建绘图上下文时出错”的内容 我
我创建测试项目只是为了隔离问题,下面是结果。LoadFromFile是线程1。日志显示线程实际运行了,但之后引发了异常 Logcat屏幕截图:
源代码:经过大量测试和同事的帮助,我和同事解决了问题。解决方案不是终止线程并保持线程运行 我知道这有点奇怪。我试图关闭FreeOnTerminate,但它只控制线程对象,而不是实际的线程。似乎syncrhonized调用未进行syncrhonized。我不知道位图在何时何地被实际使用或复制。可能还有另一个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;
经过大量测试和同事的帮助,我和同事解决了这个问题。解决方案不是终止线程并保持线程运行 我知道这有点奇怪。我试图关闭FreeOnTerminate,但它只控制线程对象,而不是实际的线程。似乎syncrhonized调用未进行syncrhonized。我不知道位图在何时何地被实际使用或复制。可能还有另一个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;
这显然是一个应该在下一次更新中修复的bug。要对代码应用修复程序,请声明以下过程:
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论坛上发布了此解决方案。这显然是一个bug,应该在下一次更新中修复。要对代码应用修复程序,请声明以下过程:
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论坛上发布了此解决方案。位图来自何处?它是否与任何UI元素关联?不,线程中没有调用UI,我甚至创建了一个只有三行代码的测试项目。b:=TBitmap.Create;b、 LoadFromFile(TPath.Combine(TPath.GetDocumentPath+'koala.jpg');b、 免费的
TPath.Combine(TPath.GetDocumentPath+'koala.jpg')
应该是TPath.Combine(TPath.GetDocumentPath,'koala.jpg')
。位图来自哪里?它是否与任何UI元素关联?不,线程中没有调用UI,我甚至创建了一个只有三行代码的测试项目。b:=TBitmap.Create;b、 LoadFromFile(TPath.Combine(TPath.GetDocumentPath+'koala.jpg');b、 免费的TPath.Combine(TPath.GetDocumentPath+'koala.jpg')
应该是TPath.Combine(TPath.GetDocumentPath,'koala.jpg')
。这不是解决方案。这将阻止线程终止。我也有同样的问题,我把我的答案贴在下面。同意上面的评论这不是一个解决办法。这将阻止线程终止。我也有同样的问题,我把我的答案贴在下面。同意上面的评论