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

Откуда:
Сообщений: 4
Давно не кодил на Паскале, это все сын балуется. Подскажите, если из класса - наследника потока вызвать:

self.terminate();
self.waitFor();
self.destroy();


Этот поток заблокирует сам себя и не завершится (не произойдет события onTerminate)?
13 фев 20, 21:49    [22079609]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
makhaon
Member

Откуда: A galaxy far far away
Сообщений: 3523
VirtaOtec,

для того что бы потоку завершится это всё не нужно, достаточно просто выйти из execute. ну и нельзя вызывать destroy в обычном коде.
13 фев 20, 23:28    [22079656]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
alekcvp
Member

Откуда:
Сообщений: 1849
makhaon
VirtaOtec,
ну и нельзя вызывать destroy в обычном коде.

В обычном-то с чего вдруг?.. Если вы уверены что ссылка на объект валидная.
14 фев 20, 10:15    [22079785]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 5351
VirtaOtec
Давно не кодил на Паскале, это все сын балуется. Подскажите, если из класса - наследника потока вызвать:

self.terminate();
self.waitFor();
self.destroy();


Этот поток заблокирует сам себя и не завершится (не произойдет события onTerminate)?


1) Если этот код вызывать из Execute, то получите дедлок.

2) В цепочке Terminate -> WaitFor - > Destroy первые два вызова лишние, достаточно только Destroy, так как деструктор потока и так внури себя дергает Terminate -> WaitFor.
14 фев 20, 11:17    [22079822]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
makhaon
Member

Откуда: A galaxy far far away
Сообщений: 3523
alekcvp,

в документации явно указана рекомендация:

Do not call Destroy directly. Call Free instead.
http://docwiki.embarcadero.com/Libraries/Rio/en/System.TObject.Destroy

валидность ссылки должен проверять Free. Чем меньше тут самодеятельности - тем меньше проблем и сейчас и в будущем с возможным переносом кода.
14 фев 20, 14:40    [22080065]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
VirtaOtec
Member

Откуда:
Сообщений: 4
Нужно закрыть программу после корректного завершения потока. Чтобы это сделать, использую событие onTerminate потока, в нем закрываю программу.

  TMyThread = class(TThread)
  protected
    procedure execute(); override;
  end;

var
  th: TMyThread;

...

procedure TMyThread.execute();
begin
  while (not terminated) do
    sleep(10);
end;

procedure TForm1.threadTerminate(sender: TObject);
begin
  th.destroy();
  application.terminate();
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  th := TMyThread.create();
  th.onTerminate := threadTerminate;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  th.terminate();
end;


Программа зависает при остановке потока. Зависание происходит в th.destroy() на стандартных "terminate() -> waitFor()" TThread. Непонятно еще и то, почему если вызов waitFor() для себя же приводит к блокировке потока и его зависанию, почему этот метод используется в стандартном коде деструктора.

Объяснитесь, пожалуйста.
19 фев 20, 21:53    [22083362]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
alekcvp
Member

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

В любом случае нельзя вызывать Destroy() объекта из события этого объекта, т.к. после этого события всё равно будет выполняться код объекта.
Один из вариантов решения проблемы:

procedure TForm1.threadTerminate(sender: TObject);
begin
//  th.destroy();
  th := nil;
  application.terminate();
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  th := TMyThread.create(True);
  th.onTerminate := threadTerminate;
  th.FreeOnTerminate := True;
  th.Resume;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if th <> nil then
    th.terminate();
end;
19 фев 20, 22:28    [22083379]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1047
VirtaOtec
Нужно закрыть программу после корректного завершения потока. Чтобы это сделать, использую событие onTerminate потока, в нем закрываю программу.

  TMyThread = class(TThread)
  protected
    procedure execute(); override;
  end;

var
  th: TMyThread;

...

procedure TMyThread.execute();
begin
  while (not terminated) do
    sleep(10);
end;

procedure TForm1.threadTerminate(sender: TObject);
begin
  th.destroy();
  application.terminate();
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  th := TMyThread.create();
  th.onTerminate := threadTerminate;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  th.terminate();
end;


Программа зависает при остановке потока. Зависание происходит в th.destroy() на стандартных "terminate() -> waitFor()" TThread. Непонятно еще и то, почему если вызов waitFor() для себя же приводит к блокировке потока и его зависанию, почему этот метод используется в стандартном коде деструктора.

Объяснитесь, пожалуйста.


Странно, что зависает. Вроде по замыслу разработчиков Delphi не должно. Видать, за Тейксерой и Пачекой нужно перепроверять.
19 фев 20, 23:20    [22083398]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1047
А почему конструктор вызван без параметров?
19 фев 20, 23:22    [22083399]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 4102
DmSer
Странно, что зависает. Вроде по замыслу разработчиков Delphi не должно.
Наоборот, должно.
OnTerminate же в Synchronize вызывается, вот и получается дедлок.
20 фев 20, 01:07    [22083425]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
VirtaOtec
Member

Откуда:
Сообщений: 4
автор
Наоборот, должно.
OnTerminate же в Synchronize вызывается, вот и получается дедлок.


Зависает из-за особенностей VCL, то есть, в программе без VCL этот код не приведет к зависанию?
20 фев 20, 07:13    [22083461]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1047
YuRock
DmSer
Странно, что зависает. Вроде по замыслу разработчиков Delphi не должно.
Наоборот, должно.
OnTerminate же в Synchronize вызывается, вот и получается дедлок.


Я не с потолка это взял, прочитал в трудах "великих", по-моему у Тейксейра С., Пачеко К. В какой-то из редакций. К сожалению на работе доступна другая редакция и там такой хрени нет.
20 фев 20, 08:30    [22083481]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1047
Нашёл: это в редакции по Delphi 5 (в русском варианте), стр. 453. Вот выдержка из параграфа "Завершение работы потока":
Объект TThread также имеет событие OnTerminate, которое происходит при завершении работы потока. Допускается освобождение объекта TThread внутри обработчика этого события.
20 фев 20, 08:35    [22083484]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
alekcvp
Member

Откуда:
Сообщений: 1849
DmSer,

Это либо опечатка, либо маразм. Потому что после выполнения события мы вернёмся куда? В уничтоженный объект?
20 фев 20, 09:52    [22083529]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 5351
alekcvp
DmSer,

Это либо опечатка, либо маразм.
+1
20 фев 20, 11:34    [22083605]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
kealon(Ruslan)
Member

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

есть вариант с FreeOnTerminate, но он сам по себе не торт
20 фев 20, 11:41    [22083610]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
DmSer
Member

Откуда: Пенза
Сообщений: 1047
alekcvp
DmSer,

Это либо опечатка, либо маразм. Потому что после выполнения события мы вернёмся куда? В уничтоженный объект?


Видимо автору такой маразм и попался :)
20 фев 20, 11:47    [22083617]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
softwarer
Member

Откуда: 127.0.0.1
Сообщений: 60759
Блог
alekcvp
Это либо опечатка, либо маразм. Потому что после выполнения события мы вернёмся куда? В уничтоженный объект?

А что такое "вернёмся в объект"?
20 фев 20, 12:36    [22083676]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
istrebitel
Member

Откуда:
Сообщений: 32
function ThreadProc(const Thread: TThread): Integer;
var
  FreeThread: Boolean;
begin
  TThread.FCurrentThread := Thread;
  try
    Thread.FStarted := True;
    if not Thread.Terminated then
    try
      Thread.Execute;
    except
      Thread.FFatalException := AcquireExceptionObject;
    end;
  finally
    Result := Thread.FReturnValue;
    FreeThread := Thread.FFreeOnTerminate;
    Thread.DoTerminate; // После вызова OnTerminate происходит ещё куча вещей
    Thread.FFinished := True;
    SignalSyncEvent;
    if FreeThread then
    begin
      Thread.DisposeOf;
    end;
{$IFDEF USE_LIBICU}
    // Destroy Collator Cache
    if IsICUAvailable then
      ClearCollatorCache;
{$ENDIF}
    EndThread(Result);
  end;
end;
20 фев 20, 12:58    [22083701]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 5351
softwarer
alekcvp
Это либо опечатка, либо маразм. Потому что после выполнения события мы вернёмся куда? В уничтоженный объект?

А что такое "вернёмся в объект"?
В данном случае имеется ввиду туда, куда указывает стрелка

К сообщению приложен файл. Размер - 9Kb
20 фев 20, 16:00    [22083942]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
kloun02
Member

Откуда:
Сообщений: 7137
Квейд,
[:|||||||||:]
20 фев 20, 16:05    [22083948]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11498
DmSer
Нашёл: это в редакции по Delphi 5
Нужно смотреть как было в Д5. Но сейчас можно вызывать Destroy если эти две строчки поменять местами
    Thread.DoTerminate;
    Thread.FFinished := True;
20 фев 20, 18:28    [22084096]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
alekcvp
Member

Откуда:
Сообщений: 1849
softwarer
alekcvp
Это либо опечатка, либо маразм. Потому что после выполнения события мы вернёмся куда? В уничтоженный объект?

А что такое "вернёмся в объект"?

Имеется в виду очередь выполнения команд, я хз как это по-умному обозвать. То что делает ассемблерная команда ret.
21 фев 20, 09:51    [22084342]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
YuRock
Member

Откуда: Донецк
Сообщений: 4102
VirtaOtec
автор
Наоборот, должно.
OnTerminate же в Synchronize вызывается, вот и получается дедлок.


Зависает из-за особенностей VCL, то есть, в программе без VCL этот код не приведет к зависанию?
Тем более, скорее всего приведет, т.к. обработка Synchronize происходит в VCL-ном цыкле обработки сообщений.
Ну или самому надо будет CheckSynchronize вызывать.

А лучше не мучиться, а перестать использовать Synchronize и всё что с ним связано (всякие TThread.OnTerminate и т.п.). Это всё просто не нужно, и только приводит к проблемам.
21 фев 20, 14:53    [22084634]     Ответить | Цитировать Сообщить модератору
 Re: waitFor в потоке  [new]
VirtaOtec
Member

Откуда:
Сообщений: 4
YuRock, допустим, есть клиент-серверное приложение с отдельными потоками для обработки сокетов. Клиент/сервер время от времени генерирует событие, выводящее сообщение в лог, а внешнее приложение в ответ на это событие записывает сообщение в компонент TMemo.

При закрытии приложения из-за несинхронного закрытия потоков событие лога возникает в тот момент, когда форма уже удалена, и переменная memo содержит nil, что приводит к ошибке. Соответственно, используем onTerminate потока, чтобы в его обработчике выйти из программы - в этом случае компоненты на форме будут существовать до самого окончания работы потока.

Или это неправильный подход? Как здесь обойтись без onTerminate?
21 фев 20, 20:01    [22084889]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Delphi Ответить