Гость
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor / 25 сообщений из 48, страница 1 из 2
27.08.2021, 15:49
    #40093498
BorodaOleg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
Доброго дня!

Собственно, имеется программа (писал не я, только дорабатываю). В ней есть 4 потока (вообще их там больше, но для проведения эксперимента достаточно и их). Метод execute реализован следующим образом:
procedure CL4Module.Execute;
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
var StrMsg  : string;
    i : Integer; b : Byte;
Begin
    FDEFINE(BOX_L4,BOX_L4_SZ,True);
   while not Terminated do Begin
     FGET(BOX_L4,@m_nMsg);
     if Terminated then Exit;
     if m_nL4Synchronize = 1  then Synchronize(OnHandler)
     else EventHandler(m_nMsg);
   End;
End;


Содержимое FDEFINE
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
procedure FDEFINE(nIndex:Integer;w_lBoxSize:DWord;blSynch:Boolean);
Begin
  try
    with pHiBuff[nIndex] do begin
      if sCS=Nil then Begin
        sCS         := TCriticalSection.Create;
        SetLength(pb_mBoxCont,w_lBoxSize+3000);
        w_mEvent    := CreateEvent(nil, False, False, nil);
        w_mBoxSize  := w_lBoxSize;
        w_mBoxCSize := w_lBoxSize;
        w_mBoxWrite := 0;
        w_mBoxRead  := 0;
        w_mBoxMesCt := 0;
        w_blSynchro := blSynch;
        m_byIsEvent := False;
        ResetEvent(w_mEvent);
      end;
    end;
  except
     SClass.ToStringBox(ET_CRITICAL, 'Ошибка в utlbox.FDEFINE ');
  end;
End;


Содержимое FGET
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
function FGET(nIndex:Integer;pb_lInBox:Pointer):Integer;
Var wLng:Word;
Begin
  try
    if pHiBuff[nIndex].w_blSynchro then WaitForSingleObject(pHiBuff[nIndex].w_mEvent, INFINITE);
     Move(pHiBuff[nIndex].pb_mBoxCont[pHiBuff[nIndex].w_mBoxRead],wLng,2);
     Move(pHiBuff[nIndex].pb_mBoxCont[pHiBuff[nIndex].w_mBoxRead],pb_lInBox^,wLng);
     pHiBuff[nIndex].w_mBoxRead  := pHiBuff[nIndex].w_mBoxRead + wLng;
     pHiBuff[nIndex].w_mBoxSize  := pHiBuff[nIndex].w_mBoxSize + wLng;
     pHiBuff[nIndex].w_mBoxMesCt := pHiBuff[nIndex].w_mBoxMesCt - 1;
     if(pHiBuff[nIndex].w_mBoxRead > pHiBuff[nIndex].w_mBoxCSize) then pHiBuff[nIndex].w_mBoxRead := 0;
     if pHiBuff[nIndex].w_mBoxMesCt=0 then ResetEvent(pHiBuff[nIndex].w_mEvent)
     else SetEvent(pHiBuff[nIndex].w_mEvent);
     result := wLng;
  except
    SClass.ToStringBox(ET_CRITICAL, Ошибка в utlbox.FGET ');
  end;
End;


Содержимое Destroy
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
destructor CThread.Destroy;
begin
  try
  if Suspended then begin
    TerminateThread(Self.Handle, 0);
  end;
  except
    on E : Exception do
      SendEventBox(ETA_ERROR_METR+usedColor, 'Ошибка в : CThread.Destroy: '+E.Message);
  end;
  if SenderClass <> Nil then FreeAndNil(SenderClass);
  inherited;
end;


Вызов уничтожения потока из тела основной программы:
Код: pascal
1.
2.
3.
4.
5.
//  pL4Module.Suspend;
  pL4Module.Terminate;
//  FDEFINE(BOX_L4,BOX_L4_SZ,True);
//  FPUT(BOX_L4,@m_nMsg);
  if pL4Module <> nil then FreeAndNil(pL4Module);


Процедуры FPUT и FGET служат для передачи событий между модулями. В FGET ожидание события сформировано на базе WaitForSingleObject.
При вызове pL4Module.Terminate не происходит вообще ничего, pL4Module не обнуляется. При вызове FreeAndNil(pL4Module) вызывается Destroy. Если бы была открыта строка pL4Module.Suspend (как сейчас реализовано в проекте), то поток добросовестно убивается. Но это, насколько я понимаю, не верно.
Если не вызывать Suspend, то программа попадает в destructor TThread.Destroy модуля classes, затем в WaitFor и начинает крутится в бесконечном цикле внутри TThread.WaitFor со значением WaitResult = 258.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    repeat
      { This prevents a potential deadlock if the background thread
        does a SendMessage to the foreground thread }
      if WaitResult = WAIT_OBJECT_0 + 2 then
        PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE);
      WaitResult := MsgWaitForMultipleObjects(2, H, False, 1000, QS_SENDMESSAGE);
      CheckThreadError(WaitResult <> WAIT_FAILED);
      if WaitResult = WAIT_OBJECT_0 + 1 then
        CheckSynchronize;
    until WaitResult = WAIT_OBJECT_0;


И я в упор не представляю, что может быть не верно... Может кто подскажет, или хотя бы на мысль наведет?
...
Рейтинг: 0 / 0
27.08.2021, 16:25
    #40093509
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
BorodaOleg
постоянно крутится в процедуре TThread.WaitFor

Потому, что функция FGET висит - видимо, события ждёт, вечно.

BorodaOleg
Код: pascal
1.
2.
3.
if Suspended then begin
    TerminateThread(Self.Handle, 0);
  end;


В печь. Писателю - осиновый кол в сердце.

BorodaOleg
Вызов уничтожения потока из тела основной программы:
Код: pascal
1.
2.
3.
4.
5.
//  pL4Module.Suspend;
  pL4Module.Terminate;
//  FDEFINE(BOX_L4,BOX_L4_SZ,True);
//  FPUT(BOX_L4,@m_nMsg);
  if pL4Module <> nil then FreeAndNil(pL4Module);


В печь.
Заменить на
Код: pascal
1.
FreeAndNil(pL4Module);
...
Рейтинг: 0 / 0
27.08.2021, 16:28
    #40093510
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
BorodaOleg
При вызове pL4Module.Terminate не происходит вообще ничего
Ошибаетесь. Происходит установка Terminated = True
BorodaOleg
pL4Module не обнуляется.
А должен? Серьезно?
BorodaOleg
Если бы была открыта строка pL4Module.Suspend (как сейчас реализовано в проекте), то поток добросовестно убивается
Нет. Поток брутально уничтожается. Потому, что вызовом Suspend (который вызывать для чужого потока запрещено, если вы не отладчик), а потом в деструкторе для усыпленного потока вызывается TerminateThread
BorodaOleg
Код: pascal
1.
2.
3.
  if Suspended then begin
    TerminateThread(Self.Handle, 0);
  end;

который вызывать вообще нельзя
BorodaOleg
Если не вызывать Suspend, то программа попадает в destructor TThread.Destroy модуля classes, затем в WaitFor и начинает крутится в бесконечном цикле внутри
Правильно. Потому что поток у вас находится в состоянии ожидания
BorodaOleg
Код: pascal
1.
 if pHiBuff[nIndex].w_blSynchro then WaitForSingleObject(pHiBuff[nIndex].w_mEvent, INFINITE);

и оттуда вы его не вывели.

Что нужно сделать:
1. Завести второй объект TerminateEvent и ждать в FGET двух хендлов. Если у вас все потоки останавливаются одновременно, то достаточно одного глобального события без автосброса. Если потоки останавливаются выборочно, то каждому потоку нужен свой объект
2. Написать адекватный деструктор потока
Код: pascal
1.
2.
3.
4.
5.
6.
destructor CThread.Destroy;
begin
  SetEvent(TerminateEvent)
  FreeAndNil(SenderClass);
  inherited Destroy;
end;


3. Весь код уничтожения потока сократить до одной строчки
Код: pascal
1.
FreeAndNil(pL4Module);


4. По завершению потока не забыть вызвать
Код: pascal
1.
CloseHandle(w_mEvent)


5. Строка
Код: pascal
1.
ResetEvent(w_mEvent);

лишняя
...
Рейтинг: 0 / 0
27.08.2021, 17:09
    #40093520
BorodaOleg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
BorodaOleg
Если не вызывать Suspend, то программа попадает в destructor TThread.Destroy модуля classes, затем в WaitFor и начинает крутится в бесконечном цикле внутри
Правильно. Потому что поток у вас находится в состоянии ожидания
BorodaOleg
Код: pascal
1.
 if pHiBuff[nIndex].w_blSynchro then WaitForSingleObject(pHiBuff[nIndex].w_mEvent, INFINITE);

и оттуда вы его не вывели.

Что нужно сделать:
1. Завести второй объект TerminateEvent и ждать в FGET двух хендлов. Если у вас все потоки останавливаются одновременно, то достаточно одного глобального события без автосброса. Если потоки останавливаются выборочно, то каждому потоку нужен свой объект
2. Написать адекватный деструктор потока
[src delphi]
destructor CThread.Destroy;
begin
SetEvent(TerminateEvent)
FreeAndNil(SenderClass);
inherited Destroy;
end;

Было у меня подозрение, что проблема кроется именно в том, что поток крутится в WaitForSingleObject(pHiBuff[nIndex].w_mEvent, INFINITE), вот только не знаю как его оттуда вывести. Пытался кинуть в него сообщение (FPUT(BOX_L4,@m_nMsg)) но эффекта не дало.
Вы предлагаете "Завести второй объект TerminateEvent и ждать в FGET двух хендлов", если честно, не совсем соображаю как. WaitForSingleObject, насколько я понимаю позволяет использовать только 1 event или я не прав? А если WaitForSingleObject зациклится на pHiBuff[nIndex].w_mEvent то как запустить ожидание 2-го handle?
...
Рейтинг: 0 / 0
27.08.2021, 17:19
    #40093523
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
BorodaOleg
WaitForSingleObject, насколько я понимаю позволяет использовать только 1 event
Да. Но есть еще WaitForMultipleObjects
...
Рейтинг: 0 / 0
27.08.2021, 17:28
    #40093527
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
Кто мешает вместо INFINITE указать 100 и дальше ожидать в бесконечном цикле (колхоз конечно, но работать будет):
Код: pascal
1.
2.
3.
4.
5.
6.
7.
while True do
begin
  if WaitForSingleObject(pHiBuff[nIndex].w_mEvent, 100) = WAIT_OBJECT_0 then
    Break
  else if Terminated then 
    Exit;
end;



В функцию FGET необходимо передавать объект потока, чтобы была возможность контролировать свойство Terminated. Пример такой передачи по ссылке (см. функцию ThreadWaitTimeout и доп. класс TThreadAccessTerminated). Это на случай, если функция FGET реализована в другом модуле.
Либо сделать функцию FGET методом класса CThread
...
Рейтинг: 0 / 0
28.08.2021, 14:24
    #40093625
BorodaOleg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
Попытался сделать на WaitForMultipleObjects:
Конструктор Create
Код: pascal
1.
2.
3.
4.
5.
6.
constructor CThread.Create(Bool: boolean);
begin
  inherited Create(Bool);
  . . .
  TerminateEvent := CreateEvent(nil, True, False, 'TerminateEvent');
end;


Деструктор Destroy
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
destructor CThread.Destroy;
begin
  try
{  if Suspended then begin
    TerminateThread(Self.Handle, 0);
  end;}
  SetEvent(TerminateEvent);
  except
    on E : Exception do
      SendEventBox(ETA_ERROR_METR+usedColor, 'Ошибка в : CThread.Destroy: '+E.Message);
  end;
  FreeAndNil(SenderClass);
  inherited;
end;


Функция FGETMULT
Код: 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.
function FGETMULT(nIndex:Integer; pb_lInBox:Pointer; AE: ArrayEvents):Integer;
Var wLng:Word;
Begin
  try
    case WaitForMultipleObjects(2, @AE, False, 1) of
      WAIT_OBJECT_0:
        begin
          Move(pHiBuff[nIndex].pb_mBoxCont[pHiBuff[nIndex].w_mBoxRead],wLng,2);
          Move(pHiBuff[nIndex].pb_mBoxCont[pHiBuff[nIndex].w_mBoxRead],pb_lInBox^,wLng);
          pHiBuff[nIndex].w_mBoxRead  := pHiBuff[nIndex].w_mBoxRead + wLng;
          pHiBuff[nIndex].w_mBoxSize  := pHiBuff[nIndex].w_mBoxSize + wLng;
          pHiBuff[nIndex].w_mBoxMesCt := pHiBuff[nIndex].w_mBoxMesCt - 1;
          if(pHiBuff[nIndex].w_mBoxRead > pHiBuff[nIndex].w_mBoxCSize) then pHiBuff[nIndex].w_mBoxRead := 0;
          if pHiBuff[nIndex].w_mBoxMesCt=0 then ResetEvent(AE[0]) // ResetEvent(pHiBuff[nIndex].w_mEvent)
          else SetEvent(pHiBuff[nIndex].w_mEvent);
          result := wLng;
        end;
      WAIT_OBJECT_0 + 1:
        begin
          ResetEvent(AE[1]);
          Exit;
        end;
    end;
  except
    SClass.ToStringBox(ET_CRITICAL, 'Ошибка в utlbox.FGETMULT ');
  end;
End;


Описание массива в Type
Код: pascal
1.
ArrayEvents = array[0..1] of THandle;


и в классе
Код: pascal
1.
2.
     FEvents        : ArrayEvents;
     TerminateEvent : THandle;


Ну и собственно, сам вызов в Execute
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
procedure CL4Module.Execute;
Begin
   FDEFINE(BOX_L4,BOX_L4_SZ,True);
   while not Terminated do Begin
     FEvents[0] := pHiBuff[BOX_L4].w_mEvent;
     FEvents[1] := TerminateEvent;
     FGETMULT(BOX_L4, @m_nMsg, FEvents);
     if Terminated then Exit;
      if m_nL4Synchronize = 1  then Synchronize(OnHandler)
. . . 


и при закрытии программы
Код: pascal
1.
2.
3.
  pL4Module.Terminate;
  if pL4Module <> nil then FreeAndNil(pL4Module);
  . . . 


В результате:
1. Намного дольше стала запускаться программа (раза в 2-3)
2. При закрытии программы долго скачет по WaitFor, в конце-концов выдает:

28.08.2021 14:19:59 : EThread: Thread Error: Неверный дескриптор (6)
(0002CD80){knsmodule.exe} [0042DD80] utlbox.TThread.CheckThreadError (Line 9453, "utlbox" + 2) + $37
(0002CDC4){knsmodule.exe} [0042DDC4] utlbox.TThread.CheckThreadError (Line 9459, "utlbox" + 2) + $A
(0002D0C5){knsmodule.exe} [0042E0C5] utlbox.TThread.WaitFor (Line 9722, "utlbox" + 17) + $16
(0002CCBB){knsmodule.exe} [0042DCBB] utlbox.TThread.Destroy (Line 9428, "utlbox" + 6) + $3
(0096945D){knsmodule.exe} [00D6A45D] utlbox.CThread.Destroy (Line 77, "utlThread.pas" + 14) + $9
(0090D872){knsmodule.exe} [00D0E872] utlbox.CL4Module.Destroy (Line 83, "knsl4module.pas" + 13) + $9
(0000341C){knsmodule.exe} [0040441C] utlbox.m_nSpeedList + $0
. . .
Где я мог опять накосячить%(
...
Рейтинг: 0 / 0
28.08.2021, 16:20
    #40093637
asutp2
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
О, безупречный WaitFor :-) взял попкорн :-)
...
Рейтинг: 0 / 0
28.08.2021, 18:01
    #40093640
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
BorodaOleg
Код: pascal
1.
WaitForMultipleObjects(2, @AE, False, 1)

1. Должно быть
Код: pascal
1.
WaitForMultipleObjects(2, @AE, False, INFINITE)

Еще лучше
Код: pascal
1.
WaitForMultipleObjects(2, @AE[0], False, INFINITE)

но это уже не принципиально. Скорее защита от будущих потенциальных ошибок

2. Этот кусок
BorodaOleg
Код: pascal
1.
2.
3.
4.
5.
WAIT_OBJECT_0 + 1:
        begin
          ResetEvent(AE[1]);
          Exit;
        end;

выбросить вообще
3.
BorodaOleg
и при закрытии программы
Код: pascal
1.
2.
3.
  pL4Module.Terminate;
  if pL4Module <> nil then FreeAndNil(pL4Module);
  . . . 

Я же написал
_Vasilisk_
3. Весь код уничтожения потока сократить до одной строчки
Код: pascal
1.
FreeAndNil(pL4Module);


4.
BorodaOleg
2. При закрытии программы долго скачет по WaitFor, в конце-концов выдает:
28.08.2021 14:19:59 : EThread: Thread Error: Неверный дескриптор (6)
А зачем вы поставили FreeOnTerminate := True?
...
Рейтинг: 0 / 0
28.08.2021, 18:51
    #40093644
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
_Vasilisk_
BorodaOleg
и при закрытии программы
Код: pascal
1.
2.
3.
  pL4Module.Terminate;
  if pL4Module <> nil then FreeAndNil(pL4Module);
  . . . 


Я же написал
_Vasilisk_
3. Весь код уничтожения потока сократить до одной строчки
Код: pascal
1.
FreeAndNil(pL4Module);


BorodaOleg
Где я мог опять накосячить%(

Много где. Раз ты такое пишешь, даже после советов ничего не делая - значит, ты не хочешь разбираться в том, что делаешь.
А стоило бы, хотябы в азах.
Зайди, для начала, в функции FreeAndNil, методы TObject.Free и TThread.Destroy и проштудируй их.
В идеале ты в этом случае сможешь понять, почему не нужны лишние Terminate и проверки на Assigned.

И еще 2 момента:
1. Ты создал именованный эвэнт. Это не нужно, поставь вместо имени nil (опять же, из-за нечтения документации и кода). Это не очень принципиально, но всё же.
2. Если ты в конструкторе класса что-то создаёшь - значит, надо убивать это в деструкторе, логика такая. Ты TerminateEvent создал, а убить забыл. Это лучше сделать после inherited Destroy (ведь пока он не выполнится - еще возможно его использование), и это касается всего.
Т.е. примерно такой:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
destructor CThread.Destroy;
begin
  Terminate; // Важно - Для того, чтобы сразу после сработки TerminateEvent переменная Terminated уже была выставлена
  SetEvent(TerminateEvent);
  FreeAndNil(SenderClass); // Это тоже надо переносить после inherited Destroy!!!
  inherited Destroy;
  CloseHandle( TerminateEvent );
end;
...
Рейтинг: 0 / 0
28.08.2021, 19:14
    #40093647
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
YuRock
Код: pascal
1.
 Terminate; // Важно - Для того, чтобы сразу после сработки TerminateEvent переменная Terminated уже была выставлена

Согласен. Хотя событие без автосброса, но так лучше
...
Рейтинг: 0 / 0
29.08.2021, 14:07
    #40093673
BorodaOleg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
Спасибо всем кто подсказал/научил, все заработало! :)
Осталось еще 18 потоков привести к общему знаменателю, и все Ок! :)
...
Рейтинг: 0 / 0
29.08.2021, 14:20
    #40093674
BorodaOleg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
_Vasilisk_

. . .
4.
BorodaOleg
2. При закрытии программы долго скачет по WaitFor, в конце-концов выдает:
28.08.2021 14:19:59 : EThread: Thread Error: Неверный дескриптор (6)
А зачем вы поставили FreeOnTerminate := True?

Читал раньше:

//Можно указать что после завершения кода поток завершится автоматически:
MyThread.FreeOnTerminate:=true;

А так как я потоки использовал без WaitFor, меня это устраивало.
...
Рейтинг: 0 / 0
29.08.2021, 14:39
    #40093675
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
BorodaOlegЧитал раньше://Можно указать что после завершения кода поток
завершится автоматически:MyThread.FreeOnTerminate:=true
Никогда больше не посещайте ресурс где Вы прочли эту глупость.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
29.08.2021, 14:52
    #40093678
BorodaOleg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
YuRock

Много где. Раз ты такое пишешь, даже после советов ничего не делая - значит, ты не хочешь разбираться в том, что делаешь.
А стоило бы, хотябы в азах.
Зайди, для начала, в функции FreeAndNil, методы TObject.Free и TThread.Destroy и проштудируй их.
В идеале ты в этом случае сможешь понять, почему не нужны лишние Terminate и проверки на Assigned.


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;


Это, на случай, из исходников Delphi 7, файл SysUtils.pas. Я в курсе, что даже с nil FreeAndNil не ляснется, но вот я в этом проекте неоднократно встречался когда объект создается в классе A, передается в класс B, а оттуда в класс С, где его добросовестно убивают (не нужен стал, видать), а потом пытаются убить еще и в классе A. А чтобы "глупая ошибка" Access violation не выскакивала, они его в пустой try..except упаковывают. Как это можно отследить, я так и не смог допетрить. Лазил по всему тексту, отслеживал пустые исключения.

YuRock

И еще 2 момента:
. . .
2. Если ты в конструкторе класса что-то создаёшь - значит, надо убивать это в деструкторе, логика такая. Ты TerminateEvent создал, а убить забыл. Это лучше сделать после inherited Destroy (ведь пока он не выполнится - еще возможно его использование), и это касается всего.

Тут каюсь, забыл. Заколупался просто, 7-й день без выходных - мозги варить отказываются %(
...
Рейтинг: 0 / 0
29.08.2021, 14:53
    #40093679
BorodaOleg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
Dimitry Sibiryakov

BorodaOlegЧитал раньше://Можно указать что после завершения кода поток
завершится автоматически:MyThread.FreeOnTerminate:=true

Никогда больше не посещайте ресурс где Вы прочли эту глупость.


https://thedelphi.ru/les/les54.php
Не буду :)
...
Рейтинг: 0 / 0
29.08.2021, 19:58
    #40093698
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
BorodaOleg
Я в курсе, что даже с nil FreeAndNil не ляснется
Тут дело не в FreeAndNil, а в Free, которое вызывается в FreeAndNil. А в Free уже проверка на Assigned есть.

BorodaOleg
но вот я в этом проекте неоднократно встречался когда объект создается в классе A, передается в класс B, а оттуда в класс С, где его добросовестно убивают (не нужен стал, видать), а потом пытаются убить еще и в классе A. А чтобы "глупая ошибка" Access violation не выскакивала, они его в пустой try..except упаковывают.

1. Вы этом случае не поможет лишняя проверка на Assigned (разве что глобальная переменная).
2. Засовывать в try/except освобождение по мусорному адресу - это ужас, который рано или поздно аукнется, и ты получишь порчу памяти и полный крах. Надо исправлять логику проекта. Убирание говнокода помогает такому исправлению.
...
Рейтинг: 0 / 0
30.08.2021, 08:34
    #40093727
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
BorodaOleg


Жесть!

Рекомендую этот материал для изучения многопоточного программирования.
К сожалению, в нем не поднимается тема ожидания сразу нескольких событий. Но считаю, что там достаточно материала, чтобы можно было самостоятельно разобраться с WaitForMultipleObjects и MsgWaitForMultipleObjects.

хотя автору это уже не нужно...
...
Рейтинг: 0 / 0
30.08.2021, 11:55
    #40093779
ъъъъъ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
DmSer
Жесть

Виноват тот, кто придумал TThread. От него у новичков все беды.
...
Рейтинг: 0 / 0
30.08.2021, 13:37
    #40093798
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
ъъъъъ
DmSer
Жесть

Виноват тот, кто придумал TThread. От него у новичков все беды.


Да вот как-то async/await не сразу изобрели. В последние 10 лет появляются то в одном, то в другом языке. А ведь именно это является панацеей от необходимости связываться с многопоточным программированием.
...
Рейтинг: 0 / 0
30.08.2021, 13:43
    #40093800
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
Зачем было что-то изобретать если есть простой и понятный beginthread(ex)?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
30.08.2021, 13:53
    #40093804
ъъъъъ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
Dimitry Sibiryakov
Зачем было что-то изобретать если есть простой и понятный beginthread(ex)?

Покойный Архангельский про TThread писал.
...
Рейтинг: 0 / 0
30.08.2021, 14:28
    #40093819
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
Dimitry Sibiryakov

Зачем было что-то изобретать если есть простой и понятный beginthread(ex)?


Доп. потоки в действительности нужны только для каких-то вычислений и обработки информации. Основные причины, когда мы их используем - это обмен по сети, обмен с устройством, запросы к базе данных, работа с файлами. Благодаря async / await обмен по сети, обмен с устройством, запросы к БД, работа с файлами перебираются в главный поток и не парят программисту мозги многопоточностью.
Колоссальный выигрыш получают сервера (например TCP или HTTP-сервер), т.к. с многопоточностью не связываешься, а код получается быстрый, простой и понятный.
...
Рейтинг: 0 / 0
30.08.2021, 14:28
    #40093820
kealon(Ruslan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
DmSer
Да вот как-то async/await не сразу изобрели. В последние 10 лет появляются то в одном, то в другом языке. А ведь именно это является панацеей от необходимости связываться с многопоточным программированием.
они как бы далеко не панацея, у них свои проблемы
но в целом что дельфи с TThread, что шарп c Async собрали все грабли с контекстом
...
Рейтинг: 0 / 0
30.08.2021, 14:31
    #40093822
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
kealon(Ruslan)
DmSer
Да вот как-то async/await не сразу изобрели. В последние 10 лет появляются то в одном, то в другом языке. А ведь именно это является панацеей от необходимости связываться с многопоточным программированием.
они как бы далеко не панацея, у них свои проблемы
но в целом что дельфи с TThread, что шарп c Async собрали все грабли с контекстом


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


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