Конференция "Начинающим" » Корректо остановить Таймеры в деструкторе.
 
  • Саня © (26.02.18 15:44) [0]
    Есть у меня класс, где в качестве полей несколько таймеров, на таймера повешены обработчики методов того же класса.

    Уничтожая класс, таймеры видимо все равно еще работают. Могут обратится к уже уничтоженному родительскому классу, получаю AV.

    Как мне корректно остановить таймеры и затем уничтожить класс.
  • DayGaykin © (26.02.18 16:01) [1]
    Free?
  • Юрий Зотов © (26.02.18 16:20) [2]
    > Как мне корректно остановить таймеры и затем уничтожить класс.

    В деструкторе класса сначала уничтожить таймеры, потом вызвать inherited.
  • Саня © (26.02.18 16:22) [3]

    > В деструкторе класса сначала уничтожить таймеры, потом вызвать
    > inherited.

    Так и делаю, но нужно наверное какую-то задержку делать.
  • Юрий Зотов © (26.02.18 16:28) [4]
    Программа однопоточная?
  • Юрий Зотов © (26.02.18 16:35) [5]
    Еще: проверьте, не вызывается ли из обработчиков таймеров код уничтожения класса? То есть, не пытается ли программа убить объект из его же метода?
  • Саня © (26.02.18 16:35) [6]

    > Юрий Зотов ©   (26.02.18 16:28) [4]
    >
    > Программа однопоточная?

    Да.
    Aдрес AV 00000000, так что вообще не понятно.
  • Юрий Зотов © (26.02.18 16:39) [7]
    procedure TMyClass.AnyProc;
    begin
     ...
     Free;
     ... // Здесь обращение к любому полю класса может дать AV
    end;
  • Саня © (26.02.18 16:58) [8]
    Странно, все должно работать нормально, я только и того, что ради эксперемента
    добавил в свой класс одно поле 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.
  • DayGaykin © (26.02.18 17:16) [9]
    MyTimer := TTimer.Create(Self);
    замени на
    MyTimer := TTimer.Create(nil);
  • Саня © (26.02.18 17:47) [10]

    > DayGaykin ©   (26.02.18 17:16) [9]
    >
    > MyTimer := TTimer.Create(Self);
    > замени на
    > MyTimer := TTimer.Create(nil);

    И Так тоже пробовал.
  • Саня © (26.02.18 17:58) [11]
    )))

    Скопировал проект на  более мощный домашний ПК и не могу добиться ошибки, хотя на том ПК на котором AV ситуация воспроизводится 10 из 10.

    Тут точно что-то с таймерами, может быть быстрее тикает на другом ПК или что-то типа того.


    > > MyTimer := TTimer.Create(nil);

    У меня первоначально так и было, так как класс у меня от TObject. Попробую унаследоваться от от TPanel и сделать наоборт

    > MyTimer := TTimer.Create(Self);

    Но это завтра только будет доступ до того ПК, сегодня на моем ошибка не вкакую не воспроизводится.
  • Юрий Зотов © (26.02.18 19:14) [12]
    MyTimer уничтожается дважды:

    1. Явно в деструкторе TMyClass.
    2. Неявно, вместе со своим владельцем.

    Отсюда и ошибка.
  • Rouse_ © (28.02.18 19:24) [13]
    В Данном коде ошибки нет (не воспроизводится). Кинь экзешник и обязательно MAP файл в архиве, только в этой ситуевине че-то снять можно, а лучше посмотри, мошт у тебя там какие пакеты неявно линкуются?
  • Rouse_ © (28.02.18 19:25) [14]
    Ну и первым делом есесно MyClass: TMyClass; убери из глобалки, может бы с этим что нам не показываешь, нахомячил
  • dmk © (28.02.18 23:03) [15]
    В пустой аппликации все норм.
  • Redmond (03.03.18 21:14) [16]
    Для начала вместо
    {...}.Free;
    всегда использовать
    FreeAndNil({...});
    Потом, что видно в отладчике? А то тоже не воспроизводится...
  • Германн © (04.03.18 02:41) [17]

    > Redmond   (03.03.18 21:14) [16]
    >
    > Для начала вместо
    > ?
    > 1
    >  
    > {...}.Free;
    >
    > всегда использовать
    > ?
    > 1
    >  
    > FreeAndNil({...});

    Почему и главное зачем?
  • Игорь Шевченко © (04.03.18 10:04) [18]
  • Rouse_ © (04.03.18 14:28) [19]
    Там же как приговор:
    "If your code requires you to use FreeAndNil to reveal and easily find bugs, then your design is wrong." :)
 
Конференция "Начинающим" » Корректо остановить Таймеры в деструкторе.
Есть новые Нет новых   [134427   +34][b:0][p:0.001]