Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / waitFor в потоке / 25 сообщений из 53, страница 1 из 3
13.02.2020, 21:49
    #39926462
VirtaOtec
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
Давно не кодил на Паскале, это все сын балуется. Подскажите, если из класса - наследника потока вызвать:

Код: pascal
1.
2.
3.
self.terminate();
self.waitFor();
self.destroy();



Этот поток заблокирует сам себя и не завершится (не произойдет события onTerminate)?
...
Рейтинг: 0 / 0
13.02.2020, 23:28
    #39926494
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
VirtaOtec,

для того что бы потоку завершится это всё не нужно, достаточно просто выйти из execute. ну и нельзя вызывать destroy в обычном коде.
...
Рейтинг: 0 / 0
14.02.2020, 10:15
    #39926575
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
makhaon
VirtaOtec,
ну и нельзя вызывать destroy в обычном коде.

В обычном-то с чего вдруг?.. Если вы уверены что ссылка на объект валидная.
...
Рейтинг: 0 / 0
14.02.2020, 11:17
    #39926598
Квейд
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
VirtaOtec
Давно не кодил на Паскале, это все сын балуется. Подскажите, если из класса - наследника потока вызвать:

Код: pascal
1.
2.
3.
self.terminate();
self.waitFor();
self.destroy();



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


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

2) В цепочке Terminate -> WaitFor - > Destroy первые два вызова лишние, достаточно только Destroy, так как деструктор потока и так внури себя дергает Terminate -> WaitFor.
...
Рейтинг: 0 / 0
14.02.2020, 14:40
    #39926730
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
alekcvp,

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

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

валидность ссылки должен проверять Free. Чем меньше тут самодеятельности - тем меньше проблем и сейчас и в будущем с возможным переносом кода.
...
Рейтинг: 0 / 0
19.02.2020, 21:53
    #39928648
VirtaOtec
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
Нужно закрыть программу после корректного завершения потока. Чтобы это сделать, использую событие onTerminate потока, в нем закрываю программу.

Код: 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.
  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() для себя же приводит к блокировке потока и его зависанию, почему этот метод используется в стандартном коде деструктора.

Объяснитесь, пожалуйста.
...
Рейтинг: 0 / 0
19.02.2020, 22:28
    #39928664
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
VirtaOtec,

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

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
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;
...
Рейтинг: 0 / 0
19.02.2020, 23:20
    #39928678
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
VirtaOtec
Нужно закрыть программу после корректного завершения потока. Чтобы это сделать, использую событие onTerminate потока, в нем закрываю программу.

Код: 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.
  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 не должно. Видать, за Тейксерой и Пачекой нужно перепроверять.
...
Рейтинг: 0 / 0
19.02.2020, 23:22
    #39928679
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
А почему конструктор вызван без параметров?
...
Рейтинг: 0 / 0
20.02.2020, 01:07
    #39928695
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
DmSer
Странно, что зависает. Вроде по замыслу разработчиков Delphi не должно.
Наоборот, должно.
OnTerminate же в Synchronize вызывается, вот и получается дедлок.
...
Рейтинг: 0 / 0
20.02.2020, 07:13
    #39928715
VirtaOtec
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
авторНаоборот, должно.
OnTerminate же в Synchronize вызывается, вот и получается дедлок.

Зависает из-за особенностей VCL, то есть, в программе без VCL этот код не приведет к зависанию?
...
Рейтинг: 0 / 0
20.02.2020, 08:30
    #39928733
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
YuRock
DmSer
Странно, что зависает. Вроде по замыслу разработчиков Delphi не должно.
Наоборот, должно.
OnTerminate же в Synchronize вызывается, вот и получается дедлок.


Я не с потолка это взял, прочитал в трудах "великих", по-моему у Тейксейра С., Пачеко К. В какой-то из редакций. К сожалению на работе доступна другая редакция и там такой хрени нет.
...
Рейтинг: 0 / 0
20.02.2020, 08:35
    #39928736
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
Нашёл: это в редакции по Delphi 5 (в русском варианте), стр. 453. Вот выдержка из параграфа "Завершение работы потока":
Объект TThread также имеет событие OnTerminate, которое происходит при завершении работы потока. Допускается освобождение объекта TThread внутри обработчика этого события.
...
Рейтинг: 0 / 0
20.02.2020, 09:52
    #39928762
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
DmSer,

Это либо опечатка, либо маразм. Потому что после выполнения события мы вернёмся куда? В уничтоженный объект?
...
Рейтинг: 0 / 0
20.02.2020, 11:34
    #39928811
Квейд
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
alekcvp
DmSer,

Это либо опечатка, либо маразм.
+1
...
Рейтинг: 0 / 0
20.02.2020, 11:41
    #39928815
kealon(Ruslan)
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
alekcvp,

есть вариант с FreeOnTerminate, но он сам по себе не торт
...
Рейтинг: 0 / 0
20.02.2020, 11:47
    #39928819
DmSer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
alekcvp
DmSer,

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


Видимо автору такой маразм и попался :)
...
Рейтинг: 0 / 0
20.02.2020, 12:36
    #39928845
softwarer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
alekcvp
Это либо опечатка, либо маразм. Потому что после выполнения события мы вернёмся куда? В уничтоженный объект?

А что такое "вернёмся в объект"?
...
Рейтинг: 0 / 0
20.02.2020, 12:58
    #39928861
istrebitel
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
Код: 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.
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;
...
Рейтинг: 0 / 0
20.02.2020, 16:00
    #39928990
Квейд
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
softwarer
alekcvp
Это либо опечатка, либо маразм. Потому что после выполнения события мы вернёмся куда? В уничтоженный объект?

А что такое "вернёмся в объект"?
В данном случае имеется ввиду туда, куда указывает стрелка
...
Рейтинг: 0 / 0
20.02.2020, 16:05
    #39928994
kloun02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
Квейд,
[:|||||||||:]
...
Рейтинг: 0 / 0
20.02.2020, 18:28
    #39929114
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
DmSer
Нашёл: это в редакции по Delphi 5
Нужно смотреть как было в Д5. Но сейчас можно вызывать Destroy если эти две строчки поменять местами
Код: pascal
1.
2.
    Thread.DoTerminate;
    Thread.FFinished := True;
...
Рейтинг: 0 / 0
21.02.2020, 09:51
    #39929296
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
softwarer
alekcvp
Это либо опечатка, либо маразм. Потому что после выполнения события мы вернёмся куда? В уничтоженный объект?

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

Имеется в виду очередь выполнения команд, я хз как это по-умному обозвать. То что делает ассемблерная команда ret.
...
Рейтинг: 0 / 0
21.02.2020, 14:53
    #39929513
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
VirtaOtec
авторНаоборот, должно.
OnTerminate же в Synchronize вызывается, вот и получается дедлок.


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

А лучше не мучиться, а перестать использовать Synchronize и всё что с ним связано (всякие TThread.OnTerminate и т.п.). Это всё просто не нужно, и только приводит к проблемам.
...
Рейтинг: 0 / 0
21.02.2020, 20:01
    #39929645
VirtaOtec
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
waitFor в потоке
YuRock, допустим, есть клиент-серверное приложение с отдельными потоками для обработки сокетов. Клиент/сервер время от времени генерирует событие, выводящее сообщение в лог, а внешнее приложение в ответ на это событие записывает сообщение в компонент TMemo.

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

Или это неправильный подход? Как здесь обойтись без onTerminate?
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / waitFor в потоке / 25 сообщений из 53, страница 1 из 3
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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