Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Зависает WaitForSingleObject  [new]
VirtaOtec
Member

Откуда:
Сообщений: 16
В каких случаях может зависать "WaitForSingleOnject(..., INFINITE);"? Вызываю destroy(); у TThread, и доходя до вызова этой функции, поток, вызвавший destroy(); другого (вложенного) потока, зависает.
18 мар 20, 21:09    [22101791]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1664
А что является хендлом?
18 мар 20, 21:58    [22101809]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
VirtaOtec
Member

Откуда:
Сообщений: 16
X-Cite, видимо, Handle завершаемого потока. Это подставляется автоматически в TThread.
18 мар 20, 22:07    [22101814]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 49515

VirtaOtec
В каких случаях может зависать "WaitForSingleOnject(..., INFINITE);"?

Когда ожидаемый объект не переходит в возбуждённое состояние. Ну или проще: когда
программист не понимает что он делает.

Posted via ActualForum NNTP Server 1.5

18 мар 20, 22:08    [22101815]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1664
VirtaOtec,

А у вас выход из Execute вложенного потока происходит? (Если там цикл бесконечный...)
18 мар 20, 22:16    [22101819]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1664
procedure TForm1.Button1Click(Sender: TObject);
begin
  var a := TThread.CreateAnonymousThread(
    procedure
    begin
      var b := TThread.CreateAnonymousThread(
        procedure
        begin
          while True do
            ;
        end
      );
      b.FreeOnTerminate := False;
      b.Start();
      Sleep(100);
      b.Free(); // Зависнет, потому что  while True do ;
    end
  );
  a.FreeOnTerminate := False;
  a.Start();
  Sleep(100);
  a.Free();
end;
18 мар 20, 22:27    [22101823]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
VirtaOtec
Member

Откуда:
Сообщений: 16
X-Cite, в том и дело, что в Execute выход происходит. Выложить код не могу, потому что программа очень большая. Пытался повторить ошибку на какой-нибудь маленькой программе, но не получается. Не получается ошибиться! Вот и думаю, может быть, кто-нибудь знает по опыту, по каким причинам могут возникать такие проблемы.
19 мар 20, 07:09    [22101884]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 26442
VirtaOtec
Вот и думаю, может быть, кто-нибудь знает по опыту, по каким причинам могут возникать такие проблемы.

Со стороны эта просьба выглядит так: "Код не покажу, угадайте - "почему?".
19 мар 20, 08:04    [22101896]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
Valery_B
Member

Откуда: Москва
Сообщений: 2014
VirtaOtec
В каких случаях может зависать "WaitForSingleOnject

Когда WaitForSingleObject ждёт поток, который делает Synchronize.

Глюк TThread в связке WaitForSingleObject

Сообщение было отредактировано: 19 мар 20, 11:03
19 мар 20, 11:03    [22101963]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 49515

VirtaOtec
по каким причинам могут возникать такие проблемы.

И ты будешь проверять каждую из туевой хучи таких причин?

Не майся дурью, в момент зависания смотри CallStack всех потоков и определяй причину дедлока.

Posted via ActualForum NNTP Server 1.5

19 мар 20, 13:34    [22102138]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
VirtaOtec
Member

Откуда:
Сообщений: 16
Все вдруг стало ясно и понятно, а как исправить - не знаю. Ситуация в следующем: есть родительский поток и другой поток, вложенный в него. Вовне происходит нечто, что заставляет вложенный поток сгенерировать некое событие, в ответ на которое родительский поток его удаляет. И, видимо, в этом проблема: так как родительский поток удаляет вложенный по его же запросу, то из-за этого вложенный и зависает на вызове "WaitFor()" - (предполагаю,) потому что вызов "WaitFor()" происходит из контекста вложенного потока.

Так ли это? Если да, то как бороть?
23 мар 20, 21:07    [22104794]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
ъъъъъ
Member

Откуда:
Сообщений: 198
VirtaOtec
Все вдруг стало ясно и понятно, а как исправить - не знаю. Ситуация в следующем: есть родительский поток и другой поток, вложенный в него. Вовне происходит нечто, что заставляет вложенный поток сгенерировать некое событие, в ответ на которое родительский поток его удаляет. И, видимо, в этом проблема: так как родительский поток удаляет вложенный по его же запросу, то из-за этого вложенный и зависает на вызове "WaitFor()" - (предполагаю,) потому что вызов "WaitFor()" происходит из контекста вложенного потока.

Так ли это? Если да, то как бороть?


Ты как про что-то, не тобой сделанное, рассказываешь.
Или ты тоже не видишь "проблемный" код, как и мы?
...
...eсли WaitFor*() делает не то, что ты от него ждешь - для чего ты его вообще используешь?
23 мар 20, 21:25    [22104806]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
VirtaOtec
Member

Откуда:
Сообщений: 16
ъъъъъ, я использую не "WaitFor()" напрямую, но вызывается он автоматически в Delphi при вызове "TThread.destroy()", и там же и зависает.
23 мар 20, 21:31    [22104810]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
VirtaOtec
Member

Откуда:
Сообщений: 16
Варианты пока такие:

1. Вызывать удаление вложенного потока в TThread.queue().
2. Поставить вложенному потоку "FreeOnTerminate := true" и удалять его через "TThread.terminate()".

Либо, еще какие-то есть?
23 мар 20, 21:40    [22104812]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 5798
VirtaOtec,

код то покажи, желательно в самом простом варианте повторения проблемы
гаданием и снятием порчи по фотографии другие люди занимаются
24 мар 20, 08:21    [22104891]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
Zelius
Member

Откуда: Россия, Москва
Сообщений: 1419
VirtaOtec,

использую простое правило - поток сам себя не удаляет, просто нотифицирует родительский о том, что он закончил работу. Как это сделать - вариантов много: через оконные сообщения, через переменные, через очереди, можно просто завершиться, а родительский раз в 100 мсек проверяет его статус и если он закончился вызывает ему Free
24 мар 20, 10:06    [22104923]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
Василий 2
Member

Откуда:
Сообщений: 1016
Как реализовано это "некое событие"?
24 мар 20, 10:51    [22104949]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
GunSmoker
Member

Откуда:
Сообщений: 3119
VirtaOtec, Как узнать почему зависла программа.

Wait Chain потоков - в студию.
24 мар 20, 15:31    [22105149]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
VirtaOtec
Member

Откуда:
Сообщений: 16
Ситуация следующая. Есть ParentThread - родительский поток и ChildThread - вложенный. ChildThread был таков:

TChildThread = class(TThread)
  private
    FOnDeleted: TNotifyEvent;
  protected
    procedure execute(); override;
  public
    constructor create();
    property onDeleted: TNotifyEvent read FOnDeleted write FOnDeleted;
end;

procedure TChildThread.execute();
begin
  sleep(6250);

  if (assigned(FOnDeleted)) then onDeleted(self);
end;


А ParentThread - таков:

TParentThread = class(TThread)
  private
    childThread: TChildThread;
  protected
    procedure execute(); override;
  public
    constructor create();
    destructor destroy(); override;
    procedure removeChild(sender: TObject);
end;

constructor TParentThread.create();
begin
  inherited create(false);

  childThread := TChildThread.create();
  childThread.onDeleted := removeChild;
end;

procedure TParentThread.removeChild(sender: TObject);
begin
  childThread.destroy();
end;


Зависает на "childThread.destroy()", если после этой строки поместить еще функцию, то до нее компилятор не дойдет. Зависновение происходит в стандартном "TThread.destroy()" на вызове "waitFor()".
24 мар 20, 20:16    [22105395]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 5798
VirtaOtec,

а по твоему обработчик TParentThread.removeChild в каком потоке вызывается и кого ждёт?

procedure TChildThread.execute();
begin
  sleep(6250);

  if (assigned(FOnDeleted)) then onDeleted(self);       ->>>>>
end;
24 мар 20, 21:13    [22105428]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 26442
VirtaOtec
constructor TParentThread.create();
begin
  childThread := TChildThread.create();

Это вызывается в основном потоке.
25 мар 20, 07:05    [22105495]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
zedxxx
Member

Откуда:
Сообщений: 5
По сути, вот что вы написали:
procedure TChildThread.execute();
begin
  if (assigned(FOnDeleted)) then Self.destroy();
end;

Но так делать нельзя.

Решение: не вызывать деструктор в OnDeleted, а просто установить некий белевый флаг CanFreeChild := True и вызывать деструктор из родительского потока в Execute:

TParentThread = class(TThread)
  private
    childThread: TChildThread;
    CanFreeChild: Boolean;           // <<< 1
  protected
    procedure execute(); override;
  public
    constructor create();
    destructor destroy(); override;
    procedure removeChild(sender: TObject);
end;

constructor TParentThread.create();
begin
  inherited create(false);

  childThread := TChildThread.create();
  childThread.onDeleted := removeChild;
end;

procedure TParentThread.removeChild(sender: TObject);
begin
  CanFreeChild := True; // <<< 2  
end;

procedure TParentThread.execute();
begin
  while not Terminated do begin
    ...
    if CanFreeChild then begin  // <<< 3
      FreeAndNil(childThread);
      CanFreeChild := False;
    end;

  end;
end;
25 мар 20, 08:26    [22105515]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11598
zedxxx
Решение: не вызывать деструктор в OnDeleted, а просто установить некий белевый флаг CanFreeChild := True и вызывать деструктор из родительского потока в Execute
FreeOnTerminated будет достаточно
25 мар 20, 14:25    [22105734]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
zedxxx
Member

Откуда:
Сообщений: 5
_Vasilisk_, Ну да. Но это синтетический и упрощённый пример того, как послать сообщение родительскому потоку о завершении работы и передать ему управление. У топикстартера с этим проблема. К тому же, в реальной жизни дочерний поток может и не нужно убивать или есть какая-то причина, почему именно родительский поток должен управлять временем жизни дочернего.
25 мар 20, 15:05    [22105760]     Ответить | Цитировать Сообщить модератору
 Re: Зависает WaitForSingleObject  [new]
X-Cite
Member

Откуда: Минск
Сообщений: 1664
VirtaOtec,

У вас в потоках выполняется что-то одноразовое действие или у вас там циклическая очередь по сути?
25 мар 20, 16:53    [22105808]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Delphi Ответить