powered by simpleCommunicator - 2.0.36     © 2025 Programmizd 02
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как правильно убивать thread
52 сообщений из 52, показаны все 3 страниц
Как правильно убивать thread
    #40127804
svd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет.

Нить используется для фильтрации. Имеет свойство FreeOnTerminated = true. Нигде не останавливается и через Synchronyze добавляет элементы в Листбокс. Сама выборка из базы имеет ограниченное количество записей: когда пользователь хочет проскролировать ниже, стартует новая нить с новым запросом.

Проблема в следующая. Когда пользователь задает фильтр, то формируется новый запрос, проверяет, что что нить еще работает, то убивает ее:

Код: 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.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
class function TFetchThread.StartThreadFetch(const aSQL: String;
  const aAction: TFetchThreadAction; var aRef: TFetchThread; const aSortDesc: Boolean;
  aDSNotify: TDataSetNotifyEvent
  ): TFetchThread;
const
  C_FETCHTHREAD_MAX_COUNT_ON_TERMINATE = 100;
var
  counter: Integer;
begin
  Result := aRef;
  if (aAction <> ftaNone) then
  begin
    counter := 0;
    while Assigned(aRef) do
    begin
      if Application.Terminated then Exit;;

      if (aAction = ftaTerminate) then
        threadTerminate( aRef );
      Sleep(10);
      Application.ProcessMessages;
      if counter > C_FETCHTHREAD_MAX_COUNT_ON_TERMINATE then Break;
    end;
  end;
  if not Assigned(aRef) then
    Result := TFetchThread.Create( aSQL, aDSNotify, aRef, aSortDesc);
end;

class function TFetchThread.threadTerminate(aRef: TFetchThread): Boolean;
begin
  Result := not isThreadRun(aRef);
  if not Result then
  begin
    aRef.FDSNotify := nil;
    TFetchThread(aRef).Terminate;
    //aRef.Suspend;
    TerminateThread(aRef.Handle, 0);
  end;

  if not Result then
  begin
    Sleep(1);
    TFetchThread(aRef).Terminate;
  end;
end;




Но умирает нить не сразу, а непонятно когда и при каких условиях. Особенно если пользователь быстро меняет фильтр. Есть какой либо путь быстро убивать?
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127807
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svdНо умирает нить не сразу, а непонятно когда и при каких условиях.

При документированных: когда проверяет флаг Terminated и выходит из метода Execute.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127816
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svd,

1. Для FreeOnTerminate-потоков практически всегда невозможно корректно работать со ссылкой на объект потока без дополнительных костылей типа зануления ссылки в OnTerminate (или как там) потока.

2. Функцию TerminateThread можно использовать лишь в очень специфических случаях, я знаю таких два:
2.1. В потоке нет выделения памяти (в т.ч. - не используются переменные автоматических типов вроде String), нет создания и манипулирования любыми ресурсами;
2.2. Это происходит непосредственно перед завершением программы, чтобы закрыться хоть как-то, не дождавшись корректного завершения потока (там запрос долгий завис, например). Т.е. когда уже пофиг на память и ресурсы - при закрытии процесса всё почистится.
Как видишь, это не твои случаи.

Корректно остановить (убить) поток можно лишь сделав его логику такой, чтобы он реагировал на какое-то событие, при убиении взводил его и проверял при этом переменную Terminated.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127828
Belotsky Serge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
svd,

что мешает завести публичное поле задания (или метод для установки задания) в классе потока, и проверять наличие нового задания в Thread.Execute? Если есть задание, выполнить его, нет - поспать немножко?
И не нужно с каждым новым запросом освобождать и запускать поток. Когда нужно убить поток, со стороны главного просто установить Terminate или через задание для завершения.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127845
svd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо за подсказки.

1. Убиваю нить, потому как если эта форма долгое время не активна (а это может быть полдня), то и данные на ней не нужны, а тем более thread.

2. Попробую вариант без FreeOnTerminate. Возможно ли заставить трэд убится в методе execute, когда цикл полностью пробежал?
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127846
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svd
2. Попробую вариант без FreeOnTerminate. Возможно ли заставить трэд убится в методе execute, когда цикл полностью пробежал?

Выйти из цикла и, соответственно, из метода Execute?..
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127851
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
svd,

нить должна завершаться сама. Об этом в MSDN написано, много. Никаких TerminateTheread(), никогда.
Например, фукция нити в рабочем цикле периодически проверяет условие завершения (флажок, сообщение). Без вариантов.
TerminateTheread() зовут лишь в очень простых случаях (выше описали), либо совсем в крайних случаях, когда остаётся лишь слить воду, сохраняя лицо.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127856
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да действительно, пусть поток будет всегда. Одно поле с фильтром, одно поле (или метод) с event-ом просыпания. Главный поток установил фильтр через крит. секцию, взвел event, всё. Поток запроса шуршит с текущим фильтром, как только закончил - сбрасывает event и засыпает до его взведения. В цикле получения еще завести флаг, который бы проверял изменение фильтра и в этом случае начинал цикл заново с новым значением
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127857
Belotsky Serge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
svd
Спасибо за подсказки.

1. Убиваю нить, потому как если эта форма долгое время не активна (а это может быть полдня), то и данные на ней не нужны, а тем более thread.

2. Попробую вариант без FreeOnTerminate. Возможно ли заставить трэд убится в методе execute, когда цикл полностью пробежал?

1. Спящий поток много ресурсов не потребляет. Проверяйте есть ли задание, если нет, то спать! :)
2. В Execute вы поток не убьете, можно убить в OnTerminate.

Я вообще не понял, зачем для вашей задачи поток. Если юзер нажал кнопку, то выполните задание. Если нужно периодически обновлять инфу в ListBox, делайте это по таймеру.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127879
svd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FreeOnTerminate = false и попробовал убивать и по событию onTerminated. Все идет хорошо, но как и прежде входит в Destroy, выполняет весь код, вконце прыгает в inherited и ждет до безобразия долго на вызове WaitFor (нормального завершения не дождался).
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127881
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
svd
FreeOnTerminate = false и попробовал убивать и по событию onTerminated. Все идет хорошо, но как и прежде входит в Destroy, выполняет весь код, вконце прыгает в inherited и ждет до безобразия долго на вызове WaitFor (нормального завершения не дождался).

Потому что вытягивать себя за волосы из болота удавалось только известному барону, и то он не делал этого заряженным дробовиком, как пытаешься сделать ты
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127885
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svd
Возможно ли заставить трэд убится в методе execute, когда цикл полностью пробежал?
Выход из - Execute - и есть окончание потока.
Перед созданием (пересозданием) просто удаляй его, и всё.
Код: pascal
1.
2.
ThreadObj.Free;
ThreadObj := TMyThread.Create;


И всё будет работать всегда, и в случае ThreadObj=nil, и Terminate будет само вызываться, когда надо.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127886
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svd
FreeOnTerminate = false и попробовал убивать и по событию onTerminated
В этом случае событие OnTerminate не нужно уже
svd
до безобразия долго на вызове WaitFor
Значит Execute крутится, не выходя по условию Terminated
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127887
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YuRock,

ТС не спрашивает, как должно быть, он спрашивает - что сделать, чтобы было так, как он хочет.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127888
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svdпопробовал убивать и по событию onTerminated

Чудак, я сказал Terminated , а не onTerminate . Если ты считаешь
разницу в три буквы несущественной - прекрати пытаться программировать, это
бесперспективняк.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127891
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
TThread - зло - (с).
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127906
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ъъъъъ
TThread - зло - (с).

Зло не TThread, а многочисленные его обвесы, которые предполагались для облегчения жизни чайникам, но на самом деле просто кладезь граблей.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127911
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Fr0sT-Brutal,

я так и написал.

Если бы люди думали о нитях не как о волшебных объектах, а использовали CreateThread() из kernel32.dll, они бы хоть раз прочли https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127915
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Смена одних объектов на другие не спасет от кривых рук.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127920
Zelius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svd,

Возможно это из-за Synchronize, который ждет пока его обработают в основном потоке, который ждет, пока доп. поток закончит работу. Возможно надо использовать RemoveQueuedEvents, или переделать отправку на PostMessage.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127925
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ъъъъъЕсли бы люди думали о нитях не как о волшебных объектах, а использовали
CreateThread() из kernel32.dll, они бы хоть раз прочли

Главное чтобы они не пропустили при этом мимо ушей " никогда не используйте
CreateThread() в приложениях, использующих RTL
".
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127933
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ты до сих пор свой .Execute так и не показал - а это ведь самое важное в вопросе, а вовсе не как ты создаёшь или завершаешь поток.

В целом, задача решается так:
- При смене фильтра: если есть старый поток - делай ему .Terminate, но не жди его, сразу запускай новый
- Если надо остановить поток - делай ему .Terminate и забывай ссылку
- В самом потоке проверяй .Terminated в .Execute
- При выходе из потока - вызывай OnTerminate для того места, где у тебя ссылка на поток. Если ссылка = ты, то скидывай результаты на UI, если ссылка = не ты, то просто удаляй результаты. В конце удали себя

Таким образом, суть тут в том, что когда тебе надо "уничтожить поток", ты просто ставишь ему флажок и идёшь дальше. Сам поток увидит этот флажок после и завершится - тоже когда-то потом, тебе уже не важно когда. Т.е. в один момент времени у тебя может работать два (а иногда и более) потоков для фильтров: один из них - текущий, а остальные - в процессе завершения.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127941
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GunSmoker
ты просто ставишь ему флажок и идёшь дальше. Сам поток увидит этот флажок после и завершится - тоже когда-то потом, тебе уже не важно когда.

А если ТС в треде использует объекты формы? Пишет, что листбокс заполняет. Форму убил - и нет листбокса.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40127946
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проблемы не увидел.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128014
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да просто onTerminate вызывается через Synch, и ТС из него пытается прибить себя же, а деструктор через WaitFor бесконечно ждет окончания. Схема архитектурно кривая
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128051
svd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
@GunSmoker
авторТы до сих пор свой .Execute так и не показал - а это ведь самое важное в вопросе, а вовсе не как ты создаёшь или завершаешь поток.
каюсь и исправляюсь.


автор- При смене фильтра: если есть старый поток - делай ему .Terminate, но не жди его, сразу запускай новый
- Если надо остановить поток - делай ему .Terminate и забывай ссылку
- В самом потоке проверяй .Terminated в .Execute
- При выходе из потока - вызывай OnTerminate для того места, где у тебя ссылка на поток. Если ссылка = ты, то скидывай результаты на UI, если ссылка = не ты, то просто удаляй результаты. В конце удали себя

так и делал. Назначил обработчик на OnTerminate. в нем сделал Free для объекта. В Execute добавил в конце цикла фетчинга Terminate. Вся цепочка отрабатывет прекрасно - датасет и база закрываются и разрушаются, ссылка освобождается и аозволяет создать и запустить новую нить, но переходит в inherited Destroy и останавливается на WaitFor.

Mелкий нюанс с WaitFor портит всю работу-выполнение кода висит там ну очень долго, я даже не знаю сколько.
Естественно FASTMM рапортует о потеряной памяти как раз из этой нити. Но при ручном логировании записывается подтверждение, что объект разрушен и память свободна - видимо нестыковка по времени завершения нити и процесса.

--------------------------------------

Множественные копии нити дают тормоза. Поэтому решил перейти к совету коллеги @Fr0sT-Brutal - нить не убивать, но каждый раз менять ей SQL

Код: 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.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
procedure TFetchThread.Execute;
begin
  {$IFDEF RUNWATCH}
  AddThread(Self, 'Start>>>');
  {$ENDIF}
  try
    while not Terminated do
    begin
      if sqlChanged then
      begin
        if not DB.Connected then
          DB.Open(False);
        DS.Close;
        DS.SelectSQL.Text := getSQL;
        DS.Open;

      end;

      if DS.Active then
        if not DS.Eof then
        begin
            if Assigned(FDSNotify) then
              Synchronize(
                         procedure
                         begin
                             FDSNotify(DS);
                         end
                        ) ;
              //else
              //  Break;
            DS.Next;
        end;

      if DS.Active then
        if DS.Eof then
        begin
          DS.Close;
          suspend;
        end;

    end;  //while not Terminated

  finally
    DS.Close;
    DB.Close;
  end;

  {$IFDEF RUNWATCH}
  AddThread(Self, 'Stop<<<');
  {$ENDIF}
end;

class function TFetchThread.StartThreadFetch(const aSQL: String;
  const aAction: TFetchThreadAction; var aRef: TFetchThread; const aSortDesc: Boolean;
  aDSNotify: TDataSetNotifyEvent
  ): TFetchThread;
begin

  if Assigned(aRef) then
  begin
    Result := aRef;
    Result.Suspend;
    Result.SQL := aSQL;
    Result.Resume;
  end
  else
    Result := TFetchThread.Create( aSQL, aDSNotify, aRef, aSortDesc);
end;



При запуске стартует нормально. Сделал ограничение в запросе на показ только 3х записей за раз. При скроллинге ListBox идет запрос следующих трех и т.д. Это идея.

В реальности саспендед нить разбудить не получается. В доке нашел такую фигню:
авторWarning: Suspend is deprecated.

Pauses a running thread. Suspend was intended to be used by debuggers and is deprecated in RAD Studio XE, in the year 2010.

Call Suspend to temporarily halt the execution of the thread. To resume execution after a call to Suspend, call Resume. Calls to Suspend can be nested; Resume must be called the same number of times Suspend was called before the thread resumes execution.

Warning: The Resume and Suspend methods should only be used for debugging purposes. Suspending a thread using Suspend can lead to deadlocks and undefined behavior within your application. Proper thread synchronization techniques should be based on TEvent and TMutex.

... и по resume поток более не просыпается. Как тогда "усыплять" нить?
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128052
svd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
два раза запостил..
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128059
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svdКак тогда "усыплять" нить?

TQueue.Wait.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128061
svd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

авторTQueue.Wait.

нигде не нашел такого класса. Это что то нестандартное? Можно пример как с этим работать?
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128062
Belotsky Serge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
svd
Dimitry Sibiryakov,

авторTQueue.Wait.


нигде не нашел такого класса. Это что то нестандартное? Можно пример как с этим работать?

Не слушай ты его :) Зачем? Просто делай sleep(10) или sleep(100) в конце цикла? Тебе же условие Terminated нужно же проверять периодически!

PS: не увидел WaitFor(). Не понял зачем он нужен, ведь потока уже к этому наверняка прибит.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128065
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svdнигде не нашел такого класса.

Странно, вроде бы в свежих дельфях была очередь с ожиданием...
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128075
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
Странно, вроде бы в свежих дельфях была очередь с ожиданием...
Код: pascal
1.
2.
3.
uses System.Generics.Collections;

TThreadedQueue<T>.PopItem
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128079
svd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Belotsky Serge,

авторне увидел WaitFor(). Не понял зачем он нужен, ведь потока уже к этому наверняка прибит.

System.Classes:
Код: 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.
destructor TThread.Destroy;
begin
  if (FThreadID <> 0) and not FFinished and not FExternalThread then
  begin
    Terminate;
    if FCreateSuspended or FSuspended then
      Resume;
{$IFDEF MSWINDOWS}
    while not FStarted do
{$ELSE}
    while not ((not FCreateSuspended or FInitialSuspendDone) and FStarted) do
{$ENDIF}
      Yield;
    WaitFor;
  end;
  RemoveQueuedEvents(Self);
{$IF Defined(MSWINDOWS)}
  if (FHandle <> 0) and not FExternalThread then CloseHandle(FHandle);
{$ELSEIF Defined(POSIX)}
  // This final check is to ensure that even if the thread was never waited on
  // its resources will be freed.
  if (FThreadID <> 0) and not FExternalThread then pthread_detach(pthread_t(FThreadID));
{$IF Defined(LINUX)}
  sem_destroy(FCreateSuspendedSem);
{$ELSE}
  pthread_mutex_destroy(FCreateSuspendedMutex);
{$ENDIF LINUX or POSIX}
{$ENDIF POSIX}
  inherited Destroy;
  FFatalException.Free;
end;



Сторока 13 в коде. Он нужен, чтоб освободить доступ к какому то объекту. И он дествует до бесконечности, пока этот лок не снимет счетчик. Где он делает захват - не представляю.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128090
Belotsky Serge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
svd
Belotsky Serge,

авторне увидел WaitFor(). Не понял зачем он нужен, ведь потока уже к этому наверняка прибит.


System.Classes:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
destructor TThread.Destroy;
begin
  if (FThreadID <> 0) and not FFinished and not FExternalThread then
  begin
    Terminate;
    if FCreateSuspended or FSuspended then
      Resume;
{$IFDEF MSWINDOWS}
    while not FStarted do
{$ELSE}
    while not ((not FCreateSuspended or FInitialSuspendDone) and FStarted) do
{$ENDIF}
      Yield;
    WaitFor;
  end;
// ...
end;



Сторока 13 в коде. Он нужен, чтоб освободить доступ к какому то объекту. И он дествует до бесконечности, пока этот лок не снимет счетчик. Где он делает захват - не представляю.

Как-то все сложно для меня.
Обычно WaitFor вызывается из основного потока, что-то типа:
Код: pascal
1.
2.
3.
4.
5.
procedure TForm1.StopThread;
begin
 MyThread.Terminate; // сказать потоку - заканчивай цикл и выйди из Execute;
 MyThread.WaitFor; // Подождать пока он вывалится из Execute и вернет результат
end;



Но если у вас есть обработчик OnTerminate, то зачем WaitFor?
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128095
svd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Belotsky Serge,

если смотреть внимательно - то это не мой класс, а класс "из коробки". Я могу его изменить у себя, у коллег он не изменится. Да и не правильно это делать. И игнорировать его тоже нельзя - Destroy должен всю цепочку вложений выполнить.

Если войти в WaitFor, то там он вызывает WaitForSingeObject на этот хэндл с параметром ждать до бесконечности. То есть хэндл гдето застрял. Подозреваю в каких то списках. Могу к этому еще добавить, что иногда программа при завершении делает долгую финализацию. При ислледовании оказалось, что другая нить при определенных обстоятельствах тоже долго не завершается, но по протоколу вроде как "умирает" с освобождением ресурсов.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128102
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svdЯ могу его изменить у себя

Зато у себя ты можешь его правильно использовать, не загоняя в deadlock.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128126
Belotsky Serge
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
svd
Belotsky Serge,

если смотреть внимательно - то это не мой класс, а класс "из коробки". Я могу его изменить у себя, у коллег он не изменится. Да и не правильно это делать. И игнорировать его тоже нельзя - Destroy должен всю цепочку вложений выполнить.

Если войти в WaitFor, то там он вызывает WaitForSingeObject на этот хэндл с параметром ждать до бесконечности. То есть хэндл гдето застрял. Подозреваю в каких то списках. Могу к этому еще добавить, что иногда программа при завершении делает долгую финализацию. При ислледовании оказалось, что другая нить при определенных обстоятельствах тоже долго не завершается, но по протоколу вроде как "умирает" с освобождением ресурсов.


Ну и будете ждать до потери пульса :)
Вы откуда вызываете Free потока из OnTerminate? Так OnTerminate вызывается по выходу из Execute потока. После того как вызвали Free потока вызывается Destroy, в котором вы говорите ему завершить Execute (Terminate) и потом ждете пока он завершится. Но поток уже вышел из Excecute и обратно уже никогда не вернется :)
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128135
svd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Belotsky Serge,

не, эта схема не живая. Сделал трэд все время живой. только по окончании фетча отключается датасет и ждет прихода нового запроса.
Вроде работает, неплохо. Сейчас возникла идея использовать всего единственный фетч для показа во всех фреймах.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128147
shalamyansky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мнение сугубо личное, но проверенное практикой. Дельфийская оболочка с объектами вокруг CreateThread скорее мешает, чем помогает. Точнее, не помогает вообще никак. Пишется чистая процедура потока, запускается через CreateThread, все управление - через объекты синхронизации. Если задача потока разовая - запустил и забыл. Если задача циклическая - в конце цикла поток ждет сигнал либо на новый цикл (или не ждет - ваша логика), либо на выход. Приложению в таком случае не забыть перед закрытием дать сигнал на выход. Все.

А Delphi к этому простому делу пристраивает объекты, с которыми теперь надо репу чесать - кто, когда и как их должен освобождать?
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128154
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
shalamyansky
Мнение сугубо личное, но проверенное практикой. Дельфийская оболочка с объектами вокруг CreateThread скорее мешает, чем помогает. Точнее, не помогает вообще никак. Пишется чистая процедура потока, запускается через CreateThread, все управление - через объекты синхронизации. Если задача потока разовая - запустил и забыл. Если задача циклическая - в конце цикла поток ждет сигнал либо на новый цикл (или не ждет - ваша логика), либо на выход. Приложению в таком случае не забыть перед закрытием дать сигнал на выход. Все.

А Delphi к этому простому делу пристраивает объекты, с которыми теперь надо репу чесать - кто, когда и как их должен освобождать?

Имхо, всё же проще ч/з System.BeginThread(). 22423366
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128159
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svd
так и делал. Назначил обработчик на OnTerminate. в нем сделал Free для объекта.
Зачем? Задаете в конструкторе FreeOnTerminate := True; и не надо никаких обработчиков OnTerminate, поток сам уничтожится, и не будет при этом висеть. Как я понимаю, gunsmoker про OnTerminate написал по другому поводу, а не в связи с уничтожением TThread. (Про уничтожение он написал: "суть тут в том, что когда тебе надо "уничтожить поток", ты просто ставишь ему флажок и идёшь дальше. Сам поток увидит этот флажок после и завершится - тоже когда-то потом, тебе уже не важно когда.")

Останавливать поток удобно с помощью функций WaitForSingleObject/WaitForMultipleObjects или при помощи класса TEvent и его методов WaitFor, SetEvent, ResetEvent.
Например в коде потока, если нужно, чтобы поток что-то сделал и снова приостановился.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
  while not Terminated do
  begin
    ThreadEvent.WaitFor(INFINITE);
    if Terminated then break;
    //тут разные действия
    ...
   ThreadEvent.ResetEvent;
  end;



Из главной формы:
чтобы разбудить и поток сделал что-то:
Код: pascal
1.
ThreadEvent.SetEvent;


чтобы прекратить выполнение потока
Код: pascal
1.
2.
Thread.Terminate; //устанавливает Terminated в True
ThreadEvent.SetEvent;
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128167
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svd
Назначил обработчик на OnTerminate. в нем сделал Free для объекта.

svd
В Execute добавил в конце цикла фетчинга Terminate.

svd
Вся цепочка отрабатывет прекрасно


Разбил на отдельные цитаты для удобства, наглядности.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128168
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
svd
Если войти в WaitFor, то там он вызывает WaitForSingeObject на этот хэндл с параметром ждать до бесконечности. То есть хэндл гдето застрял. Подозреваю в каких то списках.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128169
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ъъъъъ
shalamyansky
Мнение сугубо личное, но проверенное практикой. Дельфийская оболочка с объектами вокруг CreateThread скорее мешает, чем помогает. Точнее, не помогает вообще никак. Пишется чистая процедура потока, запускается через CreateThread, все управление - через объекты синхронизации. Если задача потока разовая - запустил и забыл. Если задача циклическая - в конце цикла поток ждет сигнал либо на новый цикл (или не ждет - ваша логика), либо на выход. Приложению в таком случае не забыть перед закрытием дать сигнал на выход. Все.

А Delphi к этому простому делу пристраивает объекты, с которыми теперь надо репу чесать - кто, когда и как их должен освобождать?

Имхо, всё же проще ч/з System.BeginThread(). 22423366
Да нет разницы почти. Ту переменную (в dll, например) всё равно выставлять надо вручную, ведь многопоточный доступ к памяти может возникнуть до первого запуска BeginThread, извне.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128171
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YuRock,

кроме "той" переменной, посмотри, как функция треда в CreateThread() передается.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128181
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockмногопоточный доступ к памяти может возникнуть до первого запуска BeginThread,
извне.

Из какого "вне" если у него приложение, а не библиотека?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128192
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov
YuRockмногопоточный доступ к памяти может возникнуть до первого запуска BeginThread,
извне.

Из какого "вне" если у него приложение, а не библиотека?
Ага, я как-то не установил IsMultiThread, было смешно.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128203
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ъъъъъ
YuRock,

кроме "той" переменной, посмотри, как функция треда в CreateThread() передается.
Какая такая? Ну, соглашение вызова не такое, и что?
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128207
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
YuRockмногопоточный доступ к памяти может возникнуть до первого запуска BeginThread,
извне.

Из какого "вне" если у него приложение, а не библиотека?Я про то, что BeginThread вместо CreateThread - это не панацея в общем случае от неинициализированной переменной IsMultiThreaded.
И "в приложении, а не в библиотеке" тоже никто не запрещает инициализировать её после begin в dpr и затем использовать CreateThread.
Как минимум это быстрее на один вызов функции.
Для меня до сих пор загадка, для чего BeginThread вообще ввели. Написали бы в хелпе обязательно инициализировать IsMultiThreaded, да и всё. Тем более, что не редко приходится это делать даже в библиотеках, не стартующих потоки вообще.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128208
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock
Для меня до сих пор загадка, для чего BeginThread
Вернее, я еще понимаю - для мульти-платформенности, да только ее ввели задолго до Delphi 6 с кайликсом.
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128209
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockНаписали бы в хелпе обязательно инициализировать IsMultiThreaded, да и всё.

И 100500 чайников, забывших его прочитать, разбили бы себе голову в поисках
источника глюков. Хотя, возможно, это было бы и к лучшему.

Но они просто решили взять из VC это _beginthread(ex) до кучи чтобы облегчить
миграцию Сишников.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как правильно убивать thread
    #40128303
istrebitel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
52 сообщений из 52, показаны все 3 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как правильно убивать thread
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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