Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Поток и timer / 25 сообщений из 48, страница 1 из 2
22.11.2019, 22:46
    #39893208
LMag
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
Здравствуйте.

У меня следующий вопрос.

Как мне запускать поток каждые <опредмеченное время в секундах>?

Я создал класс потока

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
  TCountOperOrdersThread = class(TThread)
     FQuery : TpFIBQuery;
     TTans : TpFIBTransaction;
     private
        procedure RefrOrdersOper;
     protected
        procedure Execute;override;
  end;



все методы реализовал, теперь сам поток вызываю через компонент TTimer , используя метод OnTimer:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Ontimer 

.......

   CountOrdersOper := TCountOperOrdersThread.Create(true);
   CountOrdersOper.FreeOnTerminate := true;
   CountOrdersOper.Priority := tpLower;
    CountOrdersOper.Resume;

.....



Теперь через определенное время, срабатывает таймер и выполняется OnTimer, в это время происходит подвисание основной программы.

У меня вопрос как сделать так, что поток не мешал основной программе, ну то есть чтоб она не подвисала?
...
Рейтинг: 0 / 0
22.11.2019, 23:00
    #39893212
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
LMagкак сделать так, что поток не мешал основной программе, ну то есть чтоб она не подвисала?

Написать его правильно. Граблей для новичка на этом пути немерено. От огульного
использования Synchronize до сериализации вызовов Firebird API в пределах одного коннекта
клиентской библиотекой.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
22.11.2019, 23:03
    #39893213
LMag
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
Я понимаю что надо писать правильно, но как или дайте ссылку

метод execute я реализовал так
Код: pascal
1.
2.
3.
4.
5.
procedure TCountOperOrdersThread.Execute;
begin
  inherited;
  Synchronize(RefrOrdersOper);
end;
...
Рейтинг: 0 / 0
22.11.2019, 23:06
    #39893215
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
LMagметод execute я реализовал так

Ну да, худший сценарий, типичная ошибка. Человек, написавший этот неправильный код давно
умер, но дело его живёт. Synchronize надо использовать очень осторожно. Читай штатную справку.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
22.11.2019, 23:21
    #39893218
Квейд
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
LMag
Я понимаю что надо писать правильно, но как или дайте ссылку

метод execute я реализовал так
Код: pascal
1.
2.
3.
4.
5.
procedure TCountOperOrdersThread.Execute;
begin
  inherited;
  Synchronize(RefrOrdersOper);
end;

то, что ты написал, это то же самое как если бы ты вызывал RefrOrdersOper в основном потоке
...
Рейтинг: 0 / 0
22.11.2019, 23:52
    #39893227
LMag
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
А как тогда переписать
...
Рейтинг: 0 / 0
23.11.2019, 00:22
    #39893237
Док
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
LMag,

А что делает доп.поток? Какие-то циклические действия?

Если так, то можно использовать эвенты. По таймеру взводить и сбрасывать эвент, который будет соответственно замораживать/размораживать доп.поток
...
Рейтинг: 0 / 0
23.11.2019, 00:27
    #39893241
LMag
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
Док,

Ну поток опрашивает базу на количество введеных записей тем или иным оператором.

Хотел бы узнать как отдельным эвентом останавливать и запускать поток?
...
Рейтинг: 0 / 0
23.11.2019, 00:34
    #39893244
Barmaley57
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
LMag
Ну поток опрашивает базу на количество введеных записей тем или иным оператором.
Обычного события таймера хватит с головой.
...
Рейтинг: 0 / 0
23.11.2019, 00:35
    #39893246
Barmaley57
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
Ещё есть Application.OnIdle....но это, наверное, хуже...
...
Рейтинг: 0 / 0
23.11.2019, 00:46
    #39893250
LMag
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
А как запускать и останавливать поток в таймере?
...
Рейтинг: 0 / 0
23.11.2019, 00:58
    #39893252
Barmaley57
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
LMag
А как запускать и останавливать поток в таймере?
Так потоки то точно нужны? Как долго запрос считает кол-во записей? Может проще запрос подкрутить, чем в поток оборачивать?
...
Рейтинг: 0 / 0
23.11.2019, 01:17
    #39893257
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
LMagА как запускать и останавливать поток в таймере?

Никак. Поток запускается один раз и работает сам собой. Нечего делать - спит.

А опрашивать базу таким образом - плохая идея номер два. Если тебе надо оперативное
оповещение о действиях оператора - или используй POST_EVENT или организуй доставку
извещений мимо базу.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
23.11.2019, 02:54
    #39893261
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
Квейд
LMag
Я понимаю что надо писать правильно, но как или дайте ссылку

метод execute я реализовал так
Код: pascal
1.
2.
3.
4.
5.
procedure TCountOperOrdersThread.Execute;
begin
  inherited;
  Synchronize(RefrOrdersOper);
end;


то, что ты написал, это то же самое как если бы ты вызывал RefrOrdersOper в основном потоке
Гораздо хуже.
Просто вызов в основном потоке отработал бы намного быстрее, и без граблей.
Хотя зачем я это пишу, скорей всего ТС - пятничный тролль.
...
Рейтинг: 0 / 0
23.11.2019, 08:28
    #39893284
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
Даю подсказку: сначала следует проверять, не увеличилось ли последнее значение генератора с помощью
Select gen_id(genname, 0) from rdb$database
И если изменилось, тогда будет смысл пересчитывать количество записей. При этом следует также контролировать наличие последней записи по значению генератора.
В нашем колхозе так делают :)
...
Рейтинг: 0 / 0
23.11.2019, 08:30
    #39893285
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
Это работает, если записи не удаляются.
...
Рейтинг: 0 / 0
23.11.2019, 21:00
    #39893440
Док
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
LMag
Ну поток опрашивает базу на количество введеных записей тем или иным оператором.

Хотел бы узнать как отдельным эвентом останавливать и запускать поток?

можешь почитать тут
https://www.transl-gunsmoker.ru/2009/04/blog-post_17.html?m=1
http://forum.ixbt.com/topic.cgi?id=26:38680
http://www.interface.ru/home.asp?artId=6105

Я как-то игрался в эвентами, простейший тестовый проект прилагаю. Но он под Лазарь :)
...
Рейтинг: 0 / 0
23.11.2019, 23:26
    #39893478
Barmaley57
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
А почему бы не использовать готовый функционал windows:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
 TWorkThread=class(TThread)
  protected
    procedure Execute;override;
  end;

procedure TWorkThread.Execute;
begin
  while not Terminated do SleepEx(INFINITE,true);
end;


Используем так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
procedure APCProc(Data:cardinal);stdcall;
begin
  // здесь код, который необходимо выполнить в потоке
end;

//вызов
QueueUserAPC(@APCProc,<хэндл потока>,<данные>);

Сигнализацию о завершении и доставку результатов в вызывающий поток добавить по вкусу.
...
Рейтинг: 0 / 0
24.11.2019, 00:18
    #39893484
Bred eFeM
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
Barmaley57, ".... котикоф? Да вы просто не умеете их готовить!"
"" Вы должны быть внимательными при использовании функции SleepEx и кода, который прямо или косвенно создает окно. Если поток создает какие-либо окна, он должен обрабатывать сообщения. Циркулярное сообщение отправляется всем окнам в системе. Если Вы имеете поток, который использует функцию SleepEx с бесконечной задержкой, система зайдет в тупик. Два примера кода, которые косвенно создают окна - это динамический обмен данными (DDE) и модель многокомпонентных объектов (COM) CoInitialize. Поэтому, если Вы имеете поток, который создает окна, используйте MsgWaitForMultipleObjects или MsgWaitForMultipleObjectsEx, а не SleepEx.
...
Рейтинг: 0 / 0
24.11.2019, 12:55
    #39893557
Barmaley57
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
Bred eFeM, как это относится к данной теме?
С дуру то можно и х... сломать.
...
Рейтинг: 0 / 0
24.11.2019, 17:10
    #39893619
Bred eFeM
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
Barmaley57, не учите людей плохому. Если "готовый функционал windows", то это CreateThread. Вот и покажите пример с его применением для Delphi и c сообщениями/событиями для взаимодействия.
...
Рейтинг: 0 / 0
25.11.2019, 00:09
    #39893709
LMag
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
Я перенес код работы с бд в метод execute

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
 procedure ....Execute
 ......
      FQuery := TpFIBQuery.Create(nil);
      TTans := TpFIBTransaction.Create(nil);

      with TTans do begin
         TRParams.Clear;
         TRParams.Add('read_committed');
         TRParams.Add('rec_version');
         TRParams.Add('nowait');
         TRParams.Add('write');
      end;

      FQuery.Database := DM.FBase;
      TTans.DefaultDatabase := DM.FBase;
      FQuery.Transaction := TTans;

      try
         if not FQuery.Transaction.Active then FQuery.Transaction.StartTransaction;
         with FQuery do begin
             Close;
             SQL.Clear;
             SQL.Add(' запрос.... ну допустим select count(*) from <таблицы>');
            // showmessage(SQL.Text);
             ExecQuery;
         end;

         if FQuery.Transaction.Active then FQuery.Transaction.Commit;
         FQuery.Close;
      except
         if FQuery.Transaction.Active then FQuery.Transaction.Rollback;
      end;

      FreeAndNil(FQuery); FreeAndNil(TTans);



Теперь у меня программа при выполнения данного потока зависает...
убираю FQuery, программа нормально работает...

В чем проблема? Отдельно проверил вне потока, выполняется нормально...

А когда в потоке , программа виснет
...
Рейтинг: 0 / 0
25.11.2019, 00:38
    #39893712
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
1. Попробуйте создавать в потоке отдельное подключение к БД. В идеале использовать пул подключений.
2. Используйте конструкцию try..finally, удаляйте объекты в разделе finally.
...
Рейтинг: 0 / 0
25.11.2019, 01:03
    #39893714
LMag
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
Так же в начале поставил

while not Terminated do

Без этой строки программа зависала, как только запускался поток

И еще пытаюсь вывести в потоке сообщение типа

Код: pascal
1.
Showmessage(FQuery.FieldByName('cntRec').AsString);



ничего не выходит....

Что я делаю не так?
...
Рейтинг: 0 / 0
25.11.2019, 06:36
    #39893728
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поток и timer
авторЧто я делаю не так?

Зря связались с дополнительным потоком. Это не тот случай, когда можно обойтись без предварительного изучения материала.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Поток и timer / 25 сообщений из 48, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]