XE5 Android TBitmap.LoadFromStream не работает внутри потока

Я создаю простую игру для Android, используя Delphi XE5. У меня есть несколько ресурсов, PNG и Jpeg, я хотел показать экран загрузки, пока моя программа загружает все ресурсы.

Но я обнаружил, что размещение кода TBitmap.LoadFromFile или TBitmap.LoadFromStream внутри потока Android приводит к немедленному закрытию приложения и возврату в Launcher, а в режиме отладки Delphi даже не перехватывает исключение. (Код отлично работает на Windows, и без тредов на Android)

Мне пришлось открыть logcat, чтобы увидеть, что происходит, я увидел что-то вроде «Ошибка создания контекста рисования».

Мой вопрос, есть ли способ сделать экран загрузки для Android с помощью Delphi XE5? Так что экран прогресса показывает, пока изображения загружаются в память.


Я создал тестовый проект только для того, чтобы изолировать проблему, вот результат. LoadFromFile - это поток 1. Журнал предполагает, что поток действительно выполнялся, но впоследствии возникали исключения ???

Скриншот Logcat: Logcat ResultИсходный код: http://www.pockhero.com/wp-content/uploads/2013/10/threadtest1.7z


person Darkerstar    schedule 14.10.2013    source источник
comment
Откуда взялся битмап? Связан ли он с какими-либо элементами пользовательского интерфейса?   -  person David Heffernan    schedule 14.10.2013
comment
Нет, внутри потока не вызывается пользовательский интерфейс, я даже создал тестовый проект с кодом только из трех строк. б := TBitmap.Create; b.LoadFromFile(TPath.Combine(TPath.GetDocumentPath + 'koala.jpg')); б.Бесплатно;   -  person Darkerstar    schedule 14.10.2013
comment
Вместо TPath.Combine(TPath.GetDocumentPath + 'koala.jpg') должно быть TPath.Combine(TPath.GetDocumentPath, 'koala.jpg').   -  person Remy Lebeau    schedule 14.10.2013


Ответы (2)


Судя по всему, это ошибка, которая должна быть исправлена ​​в следующем обновлении. Чтобы применить исправление к вашему коду, объявите эту процедуру:

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;

и назначьте его EndThreadProc из System.Classes:

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

С помощью этого исправления вы можете установить, например, свой поток с помощью

FreeOnTerminate := true;

и тогда такой код больше не приведет к сбою приложения:

TYourThread.Create(something, somethingelse).Start;

Я должен отдать должное Антонио Тортосе за публикацию этого решения на форумах Embarcadero.

person ioan ghip    schedule 23.01.2014

После долгих испытаний и помощи коллег мы с коллегой решили проблему. Решение состоит в том, чтобы не завершать поток, а продолжать его выполнение.

Я знаю, что это немного странно. Я попытался отключить FreeOnTerminate, но он управляет только объектом потока, а не фактическим потоком. Похоже, что синхронизированный вызов не синхронизирован. Я понятия не имею, когда и где растровое изображение фактически используется или копируется. Возможно, где-то есть еще один поток графического интерфейса, поскольку скомпилированный Delphi код библиотеки Android все равно не запускается в основном потоке.

Вот рабочий код.

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;
person Darkerstar    schedule 22.10.2013
comment
Это не решение. Это предотвратит завершение вашего потока. У меня была такая же проблема, и я разместил свой ответ ниже. - person ioan ghip; 24.01.2014
comment
Согласен с комментарием выше - person Sebastian Xawery Wiśniowiecki; 26.03.2014