2013-10-14 3 views
1

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

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

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

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


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

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

+0

Откуда взялось растровое изображение? Связано ли это с любыми элементами пользовательского интерфейса? –

+0

Нет, ни один пользовательский интерфейс не вызывается в потоке, я даже создал тестовый проект, имеет только три строки кода. b: = TBitmap.Create; b.LoadFromFile (TPath.Combine (TPath.GetDocumentPath + 'koala.jpg)); b.Free; – Darkerstar

+0

'TPath.Combine (TPath.GetDocumentPath + 'koala.jpg')' должен быть 'TPath.Combine (TPath.GetDocumentPath, 'koala.jpg')' вместо этого. –

ответ

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; 
+0

Это не решение. Это приведет к остановке потока. У меня была одна и та же проблема, и я написал свой ответ ниже. –

+0

Согласен с комментарием –

3

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

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.

+0

это хорошее решение –