powered by simpleCommunicator - 2.0.37     © 2025 Programmizd 02
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
48 сообщений из 48, показаны все 2 страниц
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093498
BorodaOleg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго дня!

Собственно, имеется программа (писал не я, только дорабатываю). В ней есть 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
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093509
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093510
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093520
BorodaOleg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093523
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BorodaOleg
WaitForSingleObject, насколько я понимаю позволяет использовать только 1 event
Да. Но есть еще WaitForMultipleObjects
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093527
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кто мешает вместо 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
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093625
BorodaOleg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Попытался сделать на 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
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093637
asutp2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
О, безупречный WaitFor :-) взял попкорн :-)
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093640
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093644
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_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
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093647
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock
Код: pascal
1.
 Terminate; // Важно - Для того, чтобы сразу после сработки TerminateEvent переменная Terminated уже была выставлена

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

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

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

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

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

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

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


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

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

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


Жесть!

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

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

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

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


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

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

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


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


об чём речь?
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093828
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
о чём речь?
об организации взаимодействия с внешним миром, слишком затратно по объёму рутинного кода выходит.
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093832
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSerБлагодаря async / await обмен по сети, обмен с устройством, запросы к БД, работа
с файлами перебираются в главный поток и не парят программисту мозги
многопоточностью.

GetCurrentThreadId это подтверждает?

Технически не существует способа "перебраться в главный поток" бесконечному
циклу или ожиданию прихода ответа от сервера без того чтобы этот главный поток
не поставить колом.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093834
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
GetCurrentThreadId это подтверждает?

Технически не существует способа "перебраться в главный поток" бесконечному
циклу или ожиданию прихода ответа от сервера без того чтобы этот главный поток
не поставить колом.
технически существует, уже давно кстати, ещё с доса - раньше её кооперативная многозадачность называли
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093837
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)раньше её кооперативная многозадачность называли

Ну да, ну да.
"Как бесконечным циклом не повесить всю систему? - Не пишите бесконечных циклов!"
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093839
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

DmSerБлагодаря async / await обмен по сети, обмен с устройством, запросы к БД, работа
с файлами перебираются в главный поток и не парят программисту мозги
многопоточностью.

GetCurrentThreadId это подтверждает?

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


если бесконечный цикл не занимается майнингом, то возникают моменты, когда можно всунуть вызов await XXX, который запустит начало асинхронной операции, далее прервёт работу этого цикла и отыщет, чем бы ещё полезным можно было бы заняться основному потоку. Естественно, Sleep и WaitFor в таких циклах недопустимы!
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093840
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
- Не пишите бесконечных циклов!"
собственно так и есть, в шарпе все базовые либы переписали под такую идею
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093842
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSerЕстественно, Sleep и WaitFor в таких циклах недопустимы!

Угу, так же как TQuery.Open или epoll_wait. И в чём смысл тогда?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093843
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
DmSer
о чём речь?
об организации взаимодействия с внешним миром, слишком затратно по объёму рутинного кода выходит.


Для каждой функции, в которой есть вызов await, автоматически создаётся класс, в котором хранится состояние выполняемой операции. Это затратно по сравнению с классической машиной состояний. Но гораздо эффективнее по сравнению с многопоточным подходом.
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093844
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

DmSerЕстественно, Sleep и WaitFor в таких циклах недопустимы!

Угу, так же как TQuery.Open или epoll_wait. И в чём смысл тогда?..

[/quot]

Смысл в том, что когда вводят поддержку async/await, то для всего предлагают асинхронные аналоги, например, TQuery.OpenAsync, epoll_waitAsync. Иначе смысла нет никакого.
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093846
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSerдля всего предлагают асинхронные аналоги

Не для всего оно бывает в природе. Лисковый I/O - да, сетевой - только под
Windows да и то весьма ограниченно.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093849
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

DmSerдля всего предлагают асинхронные аналоги

Не для всего оно бывает в природе. Лисковый I/O - да, сетевой - только под
Windows да и то весьма ограниченно.


Сетевой обмен где угодно уже давно есть в асинхронном варианте. .NET, Kotlin, Rust, Go, Python, NodeJS этом активно пользуются, и далеко не только в винде.
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093850
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Иллюзия, жалкая иллюзия. Бесконечный цикл опроса текущего состояния с
ProcessMessagesasync внутри. Прогрев атмосферы.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093851
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

Иллюзия, жалкая иллюзия. Бесконечный цикл опроса текущего состояния с
ProcessMessagesasync внутри. Прогрев атмосферы.


Я не надеюсь, что в Дельфи это когда-либо появится. Скорее всего никогда не появится.
Можно не переживать.
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093854
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
DmSerБлагодаря async / await обмен по сети, обмен с устройством, запросы к БД, работа
с файлами перебираются в главный поток и не парят программисту мозги
многопоточностью.

GetCurrentThreadId это подтверждает?

Технически не существует способа "перебраться в главный поток" бесконечному
циклу или ожиданию прихода ответа от сервера без того чтобы этот главный поток
не поставить колом.Async с Callback функцией. Во всяких процессорах типа Arduino этому соответствует работа по прерываниям.
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093856
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSerЯ не надеюсь, что в Дельфи это когда-либо появится.

О чём ты? В Delphi функция async называется ProcessMessages и есть от рождения.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093857
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
Dimitry Sibiryakov

Иллюзия, жалкая иллюзия. Бесконечный цикл опроса текущего состояния с
ProcessMessagesasync внутри. Прогрев атмосферы.


Я не надеюсь, что в Дельфи это когда-либо появится. Скорее всего никогда не появится.
Можно не переживать.
Так вроде есть уже, библиотека Asynchronous Programming Library
https://docwiki.embarcadero.com/RADStudio/Sydney/en/Using_the_Asynchronous_Programming_Library
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093861
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
s62
DmSer
пропущено...


Я не надеюсь, что в Дельфи это когда-либо появится. Скорее всего никогда не появится.
Можно не переживать.
Так вроде есть уже, библиотека Asynchronous Programming Library
https://docwiki.embarcadero.com/RADStudio/Sydney/en/Using_the_Asynchronous_Programming_Library


Не сопоставимо с теми преимуществами, которые даёт async/await в других языках. Тут пул потоков с его ограничениями, а там все в одном потоке.
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093863
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

DmSerЯ не надеюсь, что в Дельфи это когда-либо появится.

О чём ты? В Delphi функция async называется ProcessMessages и есть от рождения.


Вот-вот! Одна Async-функция в Delphi уже есть. Осталось ещё миллион завезти для полноценности :)
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093867
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSerОсталось ещё миллион завезти для полноценности :)

Нет, осталось её вызов напихать в каждую сторую строку каждой первой функции.
Хотя постой-ка, местные хомячки именно так и делают.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093874
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

DmSerОсталось ещё миллион завезти для полноценности :)

Нет, осталось её вызов напихать в каждую сторую строку каждой первой функции.
Хотя постой-ка, местные хомячки именно так и делают.


Нет, выборка из очереди ожидающих асинхронных вызовов должна выполняться в методе TApplication.Run (и TForm.ShowModal).
Аналогично механизму TThread.Synchronize или TThread.Queue.
Собственно, примерно так и сделано в .NET, JS (и Python скорее всего).
В Go и Kotlin кардинально другой механизм.
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093884
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSerНет, выборка из очереди ожидающих асинхронных вызовов должна выполняться в
методе TApplication.Run (и TForm.ShowModal).

Код ProcessMessages отличается от кода ShowModal только отсуствием показа окна.
Так почему "нет"-то?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093894
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

DmSerНет, выборка из очереди ожидающих асинхронных вызовов должна выполняться в
методе TApplication.Run (и TForm.ShowModal).

Код ProcessMessages отличается от кода ShowModal только отсуствием показа окна.
Так почему "нет"-то?..


ProcessMessage это лишь вершина айсберга. И оно итак вызывается при необходимости.
...
Рейтинг: 0 / 0
Почему поток не хочет уничтожаться, постоянно крутиться в процедуре TThread.WaitFor
    #40093914
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
kealon(Ruslan)
пропущено...
об организации взаимодействия с внешним миром, слишком затратно по объёму рутинного кода выходит.


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


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