Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Вкл. таймера в потоке


Автор: Coobick 3.1.2011, 12:32
Ммм.. Почему не получается запустить таймер например так?
Код

procedure TBos.Execute;
begin
With Form1.IdHTTP1.Request do Begin
  Form1.idHTTP1.AllowCookies:=True;
     try
     Form1.IdHTTP1.Get('http://forum.vingrad.ru');

    Form1.Timer1.Enabled:=True;
end;

Ведь enabled:=False;  работает,от чего же True не работает?   smile 

Таймер запускает поток и останавливается,по окончании процедуры его надо опять запустить.. как?  smile 

Автор: Poseidon 3.1.2011, 15:18
Покажи всю TBos.Execute. finally где? До таймера или после? Возможно срабатывает ошибка, которая обрабатывается try и до таймера просто не доходит очередь. Ну и Timer.enabled:=False где? Поток вообще запускается хоть раз?

Автор: Coobick 3.1.2011, 15:52
Да без разницы.. это я просто поторопился в примере..но сути оно не меняет. 

Так тоже не пашет..  Да и потом.. Ведь оно же выключает таймер нормально..значит всё "доходит" до него нормально.  Но вот надо то как раз наоборот..надо включить..а оно ни как)..
Код

procedure TTest.Execute;
begin
try
 Form1.IdHTTP1.Get('http://google.ru');
except
end;
 Form1.Timer1.Enabled:=True;
end;

И инди тут не при чём.. вообще таймер не запускается так..  Почему?
Код

procedure TTest.Execute;
begin
     Form1.Timer1.Enabled:=(True);
end;


Добавлено через 4 минуты и 30 секунд
Цитата(Poseidon @  3.1.2011,  16:18 Найти цитируемый пост)
Ну и Timer.enabled:=False где? Поток вообще запускается хоть раз? 

Про Timer.enabled:=False я к тому это это то работает! А вот Timer1.Enabled:=True; уже нет.. Поток ессно запускается... переходит по ссылке,всё хорошо... и после тишина).

Автор: Poseidon 3.1.2011, 16:26
Тэкс, в первом примере таймер запустится только если IdHTTP1.Get выдаст ошибку. Если все пойдет гладко, то ничего не запустится, т.к. Except выполняется только если try генерирует ошибку. А вот второй код интересен. Период у таймера нормально установлен? Что у тебя вообще в OnTimer? Может тоже какое условие...

Автор: Coobick 3.1.2011, 16:45
Да в таймере без разницы что..  
Например так.
Код

procedure TForm1.FormCreate(Sender: TObject);
begin
TTest.Create(false);
end;

procedure TTest.Execute;
begin
try
Form1.IdHTTP1.Get('http://google.ru');
except
end;
  Form1.Timer1.Enabled:=True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
if Label1.Font.Color=clRed
        then Label1.Font.Color:=clLime
 else Label1.Font.Color:=clRed;
end;

Ведь если включить и поставить  там Form1.Timer1.Enabled:=false;  то срабатывает...  таймер выключается.. а с True нет.. :(

Автор: Poseidon 3.1.2011, 16:56
Ну во-первых, повторю еще раз, 12-я строка сработает только если 9-я строка выдаст ошибку. Во-вторых, я так понимаю, таймер запускается сразу при старте программы (еще в дизайнере). Тогда не понятно, где же он останавливается? Зачем выполнять 12-ю строку, если там и так True? 

В общем, тут слишком много нюансов. Давай, прикладывай проект с примером что не работает.

PS. А вообще, зачем останавливать таймер? Проверяешь в OnTimer, а не создан-ли уже поток. Если создан, то ждем еще, если нет, то создаем. И так по кругу.

Автор: Coobick 3.1.2011, 17:06
Почему если только ошибка? Ведь если надо выключить таймер,оно в ЭТОМ месте его выключает нормально...

Вот пример..  После перехода по ссылке надо что бы включился таймер..

Код

try
Form1.IdHTTP1.Get('http://google.ru');
except
 Form1.Timer1.Enabled:=True;   А ошибка вроде как тут должна сработать..  :shok 
end;
           А тут наоборот делаем нужное.. мм  
end;

Автор: Coobick 3.1.2011, 19:31
Проблема вроде как в D2010...  в D7 говорят работает всё... сам пока не могу попробовать.. Но в чём косяк,должно же быть решение от чего в 2010 не работает?

Автор: Rrader 4.1.2011, 10:53
Coobick, а ничего, что ты работаешь с VCL в дополнительном потоке без синхронизации?

Автор: Poseidon 4.1.2011, 11:32
Rrader, так синхронизация же критична для визуальных компонентов. Для не визуальных можно. Или я чего-то напутал?

Автор: Coobick 4.1.2011, 12:23
Rrader, но другие пишут что всё работает на д7... только на д2010 от чего то не работает...  Или в таком случае может ваш вариант покажите.. ?

Автор: Coobick 4.1.2011, 12:47
поставил щас д7.... и правда всё работает.  компилю этот же проект на д2010 и не работает уже.  :(  в чём косяк интересно?

Автор: Rrader 4.1.2011, 13:18
Poseidon, это заблуждение, очень кратко поясню почему. Никогда не знаешь, когда нарвешься на грабли, даже вот этот код (который в комментарий при создании нового потока идет), может отлично работать долгое время.
Код

procedure TMyThread.UpdateCaption;
begin
  Form1.Caption := 'Updated in a thread';
end;

Но иногда программа будет вылетать, или радовать "спецэффектами" - например, в каком-то диалоге шрифт изменится, пропадут компоненты и т.п. Это - результат внутренних повреждений, когда произошел конфликт основного потока и дополнительного. Почему так происходит? Ответ - VCL (не только то, что касается компонентов) в некоторых местах содержит, во-первых, глобальные данные (общий ресурс), во-вторых, обращение к этим данным никак не защищается в плане многопоточности. Общая рекомендация по работе с сомнительным насчет thread-safety кодом изложена в справке Delphi (добавлю также, что речь идет не столько о самой функции Synchronize, сколько о синхронизации вообще):
Цитата

If you are unsure whether a method call is thread-safe, call it from within the Synchronize method to ensure that it executes in the main thread.

Ни слова о VCL. Потому что причина ошибок "родилась" до VCL.

Теперь смотрим сюда: 
Код

procedure TTest.Execute;
begin
  Form1.IdHTTP1.Get('http://google.ru');

Нужно задать себе несколько вопросов. Все ли нам известно о работе метода Get? А может быть такое, что в его недрах используются глобальные данные, которые могут пересекаться с основным потоком? Хм, я не знаю. Наверное, предпочту защититься. Я нарочно взял и этот код прокрутил специально на отлов ошибок. Ну и что - словил AV. С 3-го раза.
http://forum.vingrad.ru/index.php?showtopic=219634&view=findpost&p=1573276

Автор: Poseidon 4.1.2011, 15:42
Цитата(Rrader @  4.1.2011,  13:18 Найти цитируемый пост)
Но иногда программа будет вылетать, или радовать "спецэффектами" - например, в каком-то диалоге шрифт изменится, пропадут компоненты и т.п.
Шрифт больше относится именно к визуальным компонентам. Об этом речи нет. Но вот что касается не визуальных, то как-то не приходит в голову что может быть там глобального. Мне кажется, для того, что бы изменить Enable нашего таймера, синхронизация не нужна. Тем более что мы точно знаем, что меняется этот Enable только в одном месте. Но "глюк" с D2010 интересен.



Автор: Coobick 4.1.2011, 15:50
Rrader , но как вы объясните что в D7 работает и без "этого"?
В общем делал так.. вроде работает..таймер включается. Правильно ли?  
Код

  TTest = class(TThread)
  private
  procedure SetTime;
  protected
    procedure Execute; override;
  public
  end;

....
....


procedure TForm1.FormCreate(Sender: TObject);
begin
TTest.Create(false);
end;

procedure TTest.Execute;
begin
try
Form1.IdHTTP1.Get('http://google.ru');
except
end;
  Synchronize(SetTime);
end;

procedure TTest.SetTime;
begin
  Form1.Timer1.Enabled:=True;
end;


procedure TForm1.Timer1Timer(Sender: TObject);
begin
if Label1.Font.Color=clRed
        then Label1.Font.Color:=clLime
 else Label1.Font.Color:=clRed;
end;

Автор: Rrader 4.1.2011, 17:19
Цитата(Poseidon @  4.1.2011,  21:42 Найти цитируемый пост)
Шрифт больше относится именно к визуальным компонентам.

Да не об этом речь, визуальные компоненты тут ни при чем, это результат повреждения стека. Это последствия.
Цитата(Poseidon @  4.1.2011,  21:42 Найти цитируемый пост)
Но вот что касается не визуальных, то как-то не приходит в голову что может быть там глобального.

Даже не знаю, что сказать. А для визуальных? Полагаться на такую интуицию при создании многопоточных приложений - разве можно так? smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)