Разработка под Android с использованием Delphi и FireMonkey иногда может приводить к непредвиденным ошибкам, одной из которых является ошибка "bitmap too big" при работе с компонентом TBitmap в многопоточной среде. В данной статье мы рассмотрим, как возникает эта проблема и какие шаги необходимо предпринять для её устранения.
Описание проблемы
При использовании метода MakeScreenshot компонента TControl в FireMonkey для создания скриншота в многопоточном режиме на Android может возникать ошибка "bitmap too big". Это связано с тем, что MakeScreenshot не является потокобезопасным, и его использование в потоках может приводить к конфликтам и ошибкам.
Пример кода, вызывающего ошибку
Вот пример кода, который работает корректно в однопоточном режиме, но вызывает ошибку на Android при выполнении в потоке:
procedure ScreenCaptureUsingThread;
begin
TThread.CreateAnonymousThread(
procedure ()
var
B : TBitmap;
begin
try
B := Layout1.MakeScreenshot;
try
B.SaveToFile( '...somefilepath.png' );
finally
B.Free;
end;
except
on E:Exception do
TThread.Synchronize( nil,
procedure ()
begin
ShowMessage( E.Message );
end );
end);
end);
end;
Подтвержденное решение
Решением проблемы является выполнение операций с MakeScreenshot в основном потоке, а использование потока только для сохранения полученного изображения. Это связано с тем, что операции с UI и графикой должны выполняться в основном потоке, тогда как операции с файлами могут быть вынесены в отдельный поток для ускорения работы приложения.
Пример кода с решением проблемы
procedure Capture;
begin
TThread.CreateAnonymousThread(
procedure ()
var
S : string;
B : TBitmap;
begin
try
// Создание пути для сохранения скриншота
S := '...SomePathAndFilename.png';
try
// Получение скриншота в основном потоке
TThread.Synchronize( nil,
procedure ()
begin
B := Layout1.MakeScreenshot;
// Запуск анимации для указания успешного выполнения
SomeAnimation.Start;
end );
// Сохранение изображения в файл
B.SaveToFile( S );
finally
B.Free;
end;
except
on E:Exception do
begin
TThread.Synchronize( nil,
procedure ()
begin
ShowMessage( E.Message );
end );
end;
end;
end).Start;
end;
Альтернативный ответ
В качестве альтернативного подхода можно рассмотреть использование механизма TThread.Synchronize для выполнения всех операций с TBitmap в основном потоке, что исключит возможность возникновения ошибок, связанных с потокобезопасностью.
Заключение
При работе с TBitmap в Delphi FireMonkey на Android важно помнить о потокобезопасности и выполнять операции с UI-компонентами и графикой в основном потоке. Использование многопоточности допустимо для операций, не связанных с UI, например, для сохранения файлов. Следуя этим рекомендациям, можно избежать возникновения ошибки "bitmap too big" и других подобных проблем.
При использовании компонента TBitmap в Delphi FireMonkey для Android в многопоточной среде может возникнуть ошибка 'bitmap too big', требующая корректировки кода для соблюдения потокобезопасности.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS