destructor TCamera.Destroy;
begin
StopCamera;
buttonLayout.Release;
CameraValue.Release;
inherited;
end;
procedure TCamera.StopCamera;
begin
if Thread<>nil then
begin
Thread.IdHTTP.Disconnect;
Thread.Terminate;
end;
if Camera_Image<>nil then
begin
Camera_Image.Release;
Camera_Image := nil;
CameraActive := false;
SetLength(RecordsArray, 0);
end;
end;
Он отличается от других подобных, что в при создании экземпляра в нем создается поток TCameraThread, в котором я получаю изображение с камеры.
И есть процедура FreeRoom, которой я пользуюсь для того, чтобы убивать все элементы
procedure TForm1.FreeRoom;
var
i: integer;
begin
Form1.MasterTimer.Enabled := false;
for i := Form1.RoomsScrollBox.ComponentCount - 1 downto 0 do
begin
if Form1.RoomsScrollBox.Components[i] is TEssence then
begin
(Form1.RoomsScrollBox.Components[i] as TEssence).Release;
end;
end;
SetLength(Form1.RoomElements, 0);
CurrentRoomElement := 0;
end;
Я всегда думал, что при такой конструкции будет следующий порядок, вызовется деструктор TCamera, в котором сработает функция StopCamera, которая остановит и уничтожит поток и уничтожится экземпляр класса TCamera. И все это нормально (наверное) работало до тех пор, пока я не прикрутил сервис IFMXApplicationEventService. Задача была крайне простой, при сворачивании приложения уничтожить все объекты и потоки, а при разворачивании опять все запустить.
Соответственно была сделана вот такая простая контрукция
procedure TForm1.FormCreate(Sender: TObject);
var
aFMXApplicationEventService: IFMXApplicationEventService;
begin
if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, IInterface(aFMXApplicationEventService)) then
aFMXApplicationEventService.SetApplicationEventHandler(HandleAppEvent);
end;
function TForm1.HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): boolean;
begin
case AAppEvent of
TApplicationEvent.BecameActive:
begin
Form1.CheckDefaultRoom;
end;
TApplicationEvent.WillBecomeInactive:
begin
MasterTimer.Enabled := false;
Form1.FreeRoom;
end;
end;
Result := true;
end;
Но происходит странное. Если у меня есть экземпляр TCamera с потоком внутри, то сворачивается приложение нормально, но уже не разворачивается, просто висит в памяти, или показывает черный экран. Если среди объектов нет TCamera, то все отрабатывает правильно. Судя по всему дело именно в потоке, который каким-то образом валит приложение. Еще одна странность, что я не могу отдебажить приложение, я поставил точку остановки на деструкторе, но программа не останавливается в нем, причем не только в Андроид, но и в винде.
Третий день уже бьюсь, подскажите, кто чем может, буду признателен за любую информацию.
Вопрос
gonzales
Доброго времени суток!
Не знаю, в какой раздел правильнее написать, потому как проблема из разных областей.
Собственно проблема в следующем
Есть базовый класс, TEssence
type TEssence = class(TRectangle) private procedure EssenceMouseEnter(Sender: TObject); procedure EssenceMouseLeave(Sender: TObject); public EssenceName: TLabel; EssenceImage: TImage; ImageSize: integer; constructor Create(AOwner: TComponent); Overload; constructor CreateCustom(AOwner: TComponent; X: Single; Y: Single; W: Single; H: Single; R: Single; Str_T: Single; Str_C: cardinal; Fill_C: cardinal; FontColor: cardinal; FontSize: Single; Im_size: Single; text: string); Overload; destructor Destroy; Overload; procedure SetName(Name: string); procedure SetIcon(iconnumber: integer); end;
Есть наследники от базового класса. Среди них есть есть класс TCamera
type TCamera = class(TEssence) public Thread: TCameraThread; Camera_id: byte; Snapshot_url: string; GetRecords_url: string; Record_url: string; DelFile_url: string; Camera_Image: TImage; CameraActive: boolean; CameraValue: TCircle; buttonLayout: TLayout; DetailsButton: TButton; RecordsCount: integer; RecordsArray: array of String; constructor Create(AOwner: TComponent); Overload; constructor CreateCustom(AOwner: TComponent; X: Single; Y: Single; W: Single; H: Single; R: Single; Str_T: Single; Str_C: cardinal; Fill_C: cardinal; FontColor: cardinal; FontSize: Single; Im_size: Single; text: string); Overload; destructor Destroy; Overload; procedure CameraSetURL; procedure StartCamera; procedure StopCamera; procedure CameraClick(Sender: TObject); procedure CameraRestart(Sender: TObject); procedure DownloadClick(Sender: TObject); procedure DeleteClick(Sender: TObject); procedure DetailClick(Sender: TObject); end;
destructor TCamera.Destroy; begin StopCamera; buttonLayout.Release; CameraValue.Release; inherited; end; procedure TCamera.StopCamera; begin if Thread<>nil then begin Thread.IdHTTP.Disconnect; Thread.Terminate; end; if Camera_Image<>nil then begin Camera_Image.Release; Camera_Image := nil; CameraActive := false; SetLength(RecordsArray, 0); end; end;
Он отличается от других подобных, что в при создании экземпляра в нем создается поток TCameraThread, в котором я получаю изображение с камеры.
type TCameraThread = class(TThread) private aStream: TMemoryStream; newStream: TMemoryStream; public IdConnection: TIdConnectionIntercept; IdHTTP: TIdHTTP; url: string; bmp: tbitmap; constructor Create(abmp: tbitmap); Overload; destructor Destroy; Overload; procedure Execute; override; procedure Receive(ASender: TIdConnectionIntercept; var ABuffer: TIdBytes); end;
constructor TCameraThread.Create(abmp: tbitmap); // (abmp: tbitmap; aurl: string); begin inherited Create(true); bmp := abmp; FreeOnTerminate := true; aStream := TMemoryStream.Create; newStream := TMemoryStream.Create; IdHTTP := TIdHTTP.Create; IdConnection := TIdConnectionIntercept.Create; IdHTTP.Intercept := IdConnection; IdConnection.OnReceive := Receive; end; destructor TCameraThread.Destroy; begin bmp.Free; bmp:=nil; aStream.Free; aStream:=nil; newStream.Free; newStream:=nil; IdHTTP.Free; IdHTTP:=nil; IdConnection.Free; IdConnection:=nil; inherited; end;
И есть процедура FreeRoom, которой я пользуюсь для того, чтобы убивать все элементы
procedure TForm1.FreeRoom; var i: integer; begin Form1.MasterTimer.Enabled := false; for i := Form1.RoomsScrollBox.ComponentCount - 1 downto 0 do begin if Form1.RoomsScrollBox.Components[i] is TEssence then begin (Form1.RoomsScrollBox.Components[i] as TEssence).Release; end; end; SetLength(Form1.RoomElements, 0); CurrentRoomElement := 0; end;
Я всегда думал, что при такой конструкции будет следующий порядок, вызовется деструктор TCamera, в котором сработает функция StopCamera, которая остановит и уничтожит поток и уничтожится экземпляр класса TCamera. И все это нормально (наверное) работало до тех пор, пока я не прикрутил сервис IFMXApplicationEventService. Задача была крайне простой, при сворачивании приложения уничтожить все объекты и потоки, а при разворачивании опять все запустить.
Соответственно была сделана вот такая простая контрукция
procedure TForm1.FormCreate(Sender: TObject); var aFMXApplicationEventService: IFMXApplicationEventService; begin if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, IInterface(aFMXApplicationEventService)) then aFMXApplicationEventService.SetApplicationEventHandler(HandleAppEvent); end; function TForm1.HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): boolean; begin case AAppEvent of TApplicationEvent.BecameActive: begin Form1.CheckDefaultRoom; end; TApplicationEvent.WillBecomeInactive: begin MasterTimer.Enabled := false; Form1.FreeRoom; end; end; Result := true; end;
Но происходит странное. Если у меня есть экземпляр TCamera с потоком внутри, то сворачивается приложение нормально, но уже не разворачивается, просто висит в памяти, или показывает черный экран. Если среди объектов нет TCamera, то все отрабатывает правильно. Судя по всему дело именно в потоке, который каким-то образом валит приложение. Еще одна странность, что я не могу отдебажить приложение, я поставил точку остановки на деструкторе, но программа не останавливается в нем, причем не только в Андроид, но и в винде.
Третий день уже бьюсь, подскажите, кто чем может, буду признателен за любую информацию.
Заранее спасибо!
Ссылка на комментарий
14 ответов на этот вопрос
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.