-
Есть у меня класс, где в качестве полей несколько таймеров, на таймера повешены обработчики методов того же класса.
Уничтожая класс, таймеры видимо все равно еще работают. Могут обратится к уже уничтоженному родительскому классу, получаю AV.
Как мне корректно остановить таймеры и затем уничтожить класс.
-
Free?
-
> Как мне корректно остановить таймеры и затем уничтожить класс.
В деструкторе класса сначала уничтожить таймеры, потом вызвать inherited.
-
> В деструкторе класса сначала уничтожить таймеры, потом вызвать
> inherited.
Так и делаю, но нужно наверное какую-то задержку делать.
-
Программа однопоточная?
-
Еще: проверьте, не вызывается ли из обработчиков таймеров код уничтожения класса? То есть, не пытается ли программа убить объект из его же метода?
-
> Юрий Зотов © (26.02.18 16:28) [4]
>
> Программа однопоточная?
Да.
Aдрес AV 00000000, так что вообще не понятно.
-
procedure TMyClass.AnyProc;
begin
...
Free;
... // Здесь обращение к любому полю класса может дать AV
end;
-
Странно, все должно работать нормально, я только и того, что ради эксперемента
добавил в свой класс одно поле TTimer, и повесил пустой обработчик, а вот когда вызываю Timer.Free получаю AV
все же работает, не понятно (:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TForm1 = class(TForm)
Timer1: TTimer;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TMyClass = class(TPanel)
private
MyTimer: TTimer;
procedure Tick(Sender: TObject);
public
constructor Create(AOwner: TWinControl);
destructor Destroy;override;
end;
var
Form1: TForm1;
MyClass: TMyClass;
implementation
{$R *.dfm}
constructor TMyClass.Create(AOwner: TWinControl);
begin
inherited Create(AOwner);
MyTimer := TTimer.Create(Self);
MyTimer.Interval := 300;
MyTimer.OnTimer := Tick;
end;
destructor TMyClass.Destroy;
begin
MyTimer.Free;
inherited Destroy;
end;
procedure TMyClass.Tick(Sender: TObject);
begin
Randomize;
Form1.Caption := IntToStr(Random(1000));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
MyClass := TMyClass.Create(Self);
MyClass.Parent := Self;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MyClass.Free;
end;
end.
-
MyTimer := TTimer.Create(Self);
замени на
MyTimer := TTimer.Create(nil);
-
> DayGaykin © (26.02.18 17:16) [9]
>
> MyTimer := TTimer.Create(Self);
> замени на
> MyTimer := TTimer.Create(nil);
И Так тоже пробовал.
-
)))
Скопировал проект на более мощный домашний ПК и не могу добиться ошибки, хотя на том ПК на котором AV ситуация воспроизводится 10 из 10.
Тут точно что-то с таймерами, может быть быстрее тикает на другом ПК или что-то типа того.
> > MyTimer := TTimer.Create(nil);
У меня первоначально так и было, так как класс у меня от TObject. Попробую унаследоваться от от TPanel и сделать наоборт
> MyTimer := TTimer.Create(Self);
Но это завтра только будет доступ до того ПК, сегодня на моем ошибка не вкакую не воспроизводится.
-
MyTimer уничтожается дважды:
1. Явно в деструкторе TMyClass.
2. Неявно, вместе со своим владельцем.
Отсюда и ошибка.
-
В Данном коде ошибки нет (не воспроизводится). Кинь экзешник и обязательно MAP файл в архиве, только в этой ситуевине че-то снять можно, а лучше посмотри, мошт у тебя там какие пакеты неявно линкуются?
-
Ну и первым делом есесно MyClass: TMyClass; убери из глобалки, может бы с этим что нам не показываешь, нахомячил
-
В пустой аппликации все норм.
-
Для начала вместо
{...}.Free;
всегда использовать
FreeAndNil({...});
Потом, что видно в отладчике? А то тоже не воспроизводится...
-
> Redmond (03.03.18 21:14) [16]
>
> Для начала вместо
> ?
> 1
>
> {...}.Free;
>
> всегда использовать
> ?
> 1
>
> FreeAndNil({...});
Почему и главное зачем?
-
-
Там же как приговор:
"If your code requires you to use FreeAndNil to reveal and easily find bugs, then your design is wrong." :)