powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / waitFor в потоке
53 сообщений из 53, показаны все 3 страниц
waitFor в потоке
    #39926462
VirtaOtec
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Давно не кодил на Паскале, это все сын балуется. Подскажите, если из класса - наследника потока вызвать:

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



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

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

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

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



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


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

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

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

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

валидность ссылки должен проверять Free. Чем меньше тут самодеятельности - тем меньше проблем и сейчас и в будущем с возможным переносом кода.
...
Рейтинг: 0 / 0
waitFor в потоке
    #39928648
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() для себя же приводит к блокировке потока и его зависанию, почему этот метод используется в стандартном коде деструктора.

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

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


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

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

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

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

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


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

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

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

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

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


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

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

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

Или это неправильный подход? Как здесь обойтись без onTerminate?
...
Рейтинг: 0 / 0
waitFor в потоке
    #39929706
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
При закрытии приложения из-за несинхронного закрытия потоков событие лога возникает в тот момент, когда форма уже удалена, и переменная memo содержит nil, что приводит к ошибке.


Нельзя закрывать главное окно приложения, пока есть дополнительные потоки. Варианты могут быть например такие:
а) при закрытии главного окна вызывать Free объекту потока (при этом у потока свойство FreeOnTerminate должно быть False), также нежелательно в таком потоке иметь вызовы Syncronize, т.к. может возникнуть взаимная блокировка доп. потока на этом вызове и главного потока на вызове Free.
б) если поток создаётся на короткое время, а потом уничтожается и у него FreeOnTerminate=True, то при закрытии главного окна можно проверять, работает (создан) ли этот поток и на событие OnCloseQuery выдавать на экран MessageBox, мол "у Вас запущен поток попытайтесь закрыть программу чуть позже" (и выставлять CanClose=False).
в) если поток создаётся на короткое время, а потом уничтожается и у него FreeOnTerminate=True, то при закрытии главного окна в событии OnCloseQuery можно всем запущенным потокам сообщать о необходимости закрытия (выставить глобальную переменную, которую постоянно мониторят все доп. потоки, у которых выставлен FreeOnTerminate=True). Далее вывести на экран сообщение "Вы действительно хотите закрыть программу?". Пока пользователь это сообщение нажимает, потоки успеют закрыться. Но здесь головой думать надо, не факт, что это идеальный вариант. Пользователь может и отказаться закрывать программу, тогда у программы не будет доп. потоков, о чём пользователь также желательно будет сообщить :)

Уверен, что у каждого здесь свой рецепт, как правильно завершить программу при наличии доп. потоков! Кто поделится своими рецептами? :)
...
Рейтинг: 0 / 0
waitFor в потоке
    #39929710
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вспомнил ещё один вариант, который часто использую:
1) создаёт поток (с FreeOnTerminate=True) и сохраняем ссылку на него в глобальной переменной MyThread
2) в Execute потока мониторим глобальную переменную Stop (если она = True, то делаем Exit)
3) у потока реализуем перегруженный деструктор и в нем после inherited делаем MyThread := nil
4) при закрытии главной формы выставляем Stop=True, далее в цикле проверяем значение в переменной MyThread, допустим 100 итераций по 10 мс (должно хватить). Если переменная MyThread всё ещё имеет значение, то перестаём ожидать поток, но выводим в лог сообщение. Также поступаем со всеми остальными аналогичными потоками.
...
Рейтинг: 0 / 0
waitFor в потоке
    #39929740
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а) при закрытии главного окна вызывать Free объекту потока (при этом у потока свойство FreeOnTerminate должно быть False), также нежелательно в таком потоке иметь вызовы Syncronize, т.к. может возникнуть взаимная блокировка доп. потока на этом вызове и главного потока на вызове Free.


Судя по коду метода WaitFor, такая блокировка обрабатывается и успешно разруливается.
...
Рейтинг: 0 / 0
waitFor в потоке
    #39929743
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
VirtaOtec
Или это неправильный подход?

Это крайне сомнительный и хрупкий подход, который вызывает кучу вопросов, в частности, как вообще организована запись в memo и почему поток не может проверить флаг типа "идёт выход из приложения, все заткнитесь и умрите".
...
Рейтинг: 0 / 0
waitFor в потоке
    #39929906
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
как правильно завершить программу при наличии доп. потоков! Кто поделится своими рецептами? :)


Вот единственный нормальный вариант:

DmSer
а) при закрытии главного окна вызывать Free объекту потока (при этом у потока свойство FreeOnTerminate должно быть False), также нежелательно в таком потоке иметь вызовы Syncronize, т.к. может возникнуть взаимная блокировка доп. потока на этом вызове и главного потока на вызове Free


Если потоков несколько, разных, но которые зависят друг от друга (один управляет другим) - то при таком подходе легко можно остановить их в нужном порядке.
...
Рейтинг: 0 / 0
waitFor в потоке
    #39929911
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
а) при закрытии главного окна вызывать Free объекту потока (при этом у потока свойство FreeOnTerminate должно быть False), также нежелательно в таком потоке иметь вызовы Syncronize, т.к. может возникнуть взаимная блокировка доп. потока на этом вызове и главного потока на вызове Free.


Судя по коду метода WaitFor, такая блокировка обрабатывается и успешно разруливается. Это не так. Метод, добавленный в список Synchronize, может еще не начать выполняться, а WaitFor уже вызван (при обработке главным потоком сообщения, которое обрабатывалось в момент этого добавления) - и тогда грабли выстрелят.
...
Рейтинг: 0 / 0
waitFor в потоке
    #39929925
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock
DmSer
пропущено...


Судя по коду метода WaitFor, такая блокировка обрабатывается и успешно разруливается.
Это не так. Метод, добавленный в список Synchronize, может еще не начать выполняться, а WaitFor уже вызван (при обработке главным потоком сообщения, которое обрабатывалось в момент этого добавления) - и тогда грабли выстрелят.


Я не смог воспроизвести такую проблему. Специально разработал тестовое приложение, в котором создавался доп. поток, в нём в цикле вызывался Synchronize / SendMessage (с паузой Sleep(0)), а в главном потоке таймер, который срабатывал раз в 5 мс и создавал поток либо делал ему Free. Никаких блокировок не было. Проверял на версии 10.3.3.
...
Рейтинг: 0 / 0
waitFor в потоке
    #39930168
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock,

WaitFor насколько я помню обязан дождаться начало и конец всех Synchronize перед выходом из него.
...
Рейтинг: 0 / 0
waitFor в потоке
    #39930333
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makhaon
YuRock,

WaitFor насколько я помню обязан дождаться начало и конец всех Synchronize перед выходом из него.
Это понятно. Иначе execute не закончится.
Вопрос, что будет, если waitfor уже вызван в оконном потоке, а еще не все synchronize-вызовы обработалист в execute.
Ответ - будет дедлок.
...
Рейтинг: 0 / 0
waitFor в потоке
    #39930435
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
Вспомнил ещё один вариант, который часто использую:
1) создаёт поток (с FreeOnTerminate=True) и сохраняем ссылку на него в глобальной переменной MyThread
2) в Execute потока мониторим глобальную переменную Stop (если она = True, то делаем Exit)
3) у потока реализуем перегруженный деструктор и в нем после inherited делаем MyThread := nil
4) при закрытии главной формы выставляем Stop=True, далее в цикле проверяем значение в переменной MyThread, допустим 100 итераций по 10 мс (должно хватить). Если переменная MyThread всё ещё имеет значение, то перестаём ожидать поток, но выводим в лог сообщение. Также поступаем со всеми остальными аналогичными потоками.

Очень много совершенно лишних сущностей.
Если ссылка и так есть в глоб. переменной, то вместо Stop прекрасно подойдет Terminated потока, да и обнулять ссылку на себя не нужно. И раз уж код закрытия и так ожидает, определять, что Execute завершилась, можно по ExitCode.
В общем, Terminate + WaitFor самое корректное. Если же поток может отправлять сообщения, то стоит после WaitFor запустить ProcessMessages (а для более чистой обработки лучше даже собственную выборку GetMessage, вычерпывающую только сообщения от потоков). Правда, обработчик при этом должен понимать, что программа завершается, и не делать ничего противоречащего (запуск новых потоков и т.п.)
...
Рейтинг: 0 / 0
waitFor в потоке
    #39930472
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock
makhaon
YuRock,

WaitFor насколько я помню обязан дождаться начало и конец всех Synchronize перед выходом из него.
Это понятно. Иначе execute не закончится.
Вопрос, что будет, если waitfor уже вызван в оконном потоке, а еще не все synchronize-вызовы обработалист в execute.
Ответ - будет дедлок.
не будет, см реализацию, там специальная затычка на главный поток
она обрабатывает появившиеся synchronize и сообщения
...
Рейтинг: 0 / 0
waitFor в потоке
    #39930551
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2
DmSer
Вспомнил ещё один вариант, который часто использую:
1) создаёт поток (с FreeOnTerminate=True) и сохраняем ссылку на него в глобальной переменной MyThread
2) в Execute потока мониторим глобальную переменную Stop (если она = True, то делаем Exit)
3) у потока реализуем перегруженный деструктор и в нем после inherited делаем MyThread := nil
4) при закрытии главной формы выставляем Stop=True, далее в цикле проверяем значение в переменной MyThread, допустим 100 итераций по 10 мс (должно хватить). Если переменная MyThread всё ещё имеет значение, то перестаём ожидать поток, но выводим в лог сообщение. Также поступаем со всеми остальными аналогичными потоками.

Очень много совершенно лишних сущностей.
Если ссылка и так есть в глоб. переменной, то вместо Stop прекрасно подойдет Terminated потока, да и обнулять ссылку на себя не нужно. И раз уж код закрытия и так ожидает, определять, что Execute завершилась, можно по ExitCode.
В общем, Terminate + WaitFor самое корректное. Если же поток может отправлять сообщения, то стоит после WaitFor запустить ProcessMessages (а для более чистой обработки лучше даже собственную выборку GetMessage, вычерпывающую только сообщения от потоков). Правда, обработчик при этом должен понимать, что программа завершается, и не делать ничего противоречащего (запуск новых потоков и т.п.)


Всё это хорошо при условии FreeOnTerminate=False. Ежели FreeOnTerminate=True, то обращения к доп. потоку с помощью переменной (MyThread) потенциально опасны, т.к. объект потока может исчезнуть в любой момент, никакой ExitCode в этом случае не спасёт.
...
Рейтинг: 0 / 0
waitFor в потоке
    #39930563
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если же поток может отправлять сообщения, то стоит после WaitFor запустить ProcessMessages (а для более чистой обработки лучше даже собственную выборку GetMessage, вычерпывающую только сообщения от потоков). Правда, обработчик при этом должен понимать, что программа завершается, и не делать ничего противоречащего (запуск новых потоков и т.п.)


Стараюсь не использовать метод Application.ProcessMessages, т.к. из-за него слишком уж много граблей. Всегда можно обойтись другими средствами.

А для чего делать выборку сообщений?
Что, разве при вызове WaitFor сообщения могут пропасть?

Кстати, а по какой причине при вызове WaitFor из основного потока не блокируются вызовы SendMessage из доп. потока? Из-за PeekMessage с параметром PM_NOREMOVE?
...
Рейтинг: 0 / 0
waitFor в потоке
    #39930640
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
Всё это хорошо при условии FreeOnTerminate=False. Ежели FreeOnTerminate=True, то обращения к доп. потоку с помощью переменной (MyThread) потенциально опасны, т.к. объект потока может исчезнуть в любой момент, никакой ExitCode в этом случае не спасёт.

А FreeOnTerminate=True в принципе вредная конструкция. Если она применяется, то о корректном завершении в случае принудительного закрытия приложения не может быть речи (либо же, так или иначе, вводить некий глобальный флаг, что тоже не очень хорошо).

DmSer
Стараюсь не использовать метод Application.ProcessMessages, т.к. из-за него слишком уж много граблей. Всегда можно обойтись другими средствами.

Грабли в самом деле могут быть, если их специально не прикрыть заранее.

А для чего делать выборку сообщений?
Что, разве при вызове WaitFor сообщения могут пропасть?
Если потоки завершаются из Form.OnDestroy, то конечно пропадут. Из Form.OnClose не должны
...
Рейтинг: 0 / 0
waitFor в потоке
    #39931235
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
из-за него слишком уж много граблей

Я список этих граблей давно с фонарем ищу. Можешь перечислить? :)
...
Рейтинг: 0 / 0
waitFor в потоке
    #39931258
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док
Я список этих граблей давно с фонарем ищу. Можешь перечислить? :)

Повторный запуск не рассчитанных на это процедур, если они запускаются по событию от юзера. В нашем случае - повторное закрытие, например.
...
Рейтинг: 0 / 0
waitFor в потоке
    #39931261
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2
Повторный запуск не рассчитанных на это процедур, если они запускаются по событию от юзера.

Для отсутствия таких проблем стоит пользоваться action-ами (особенно - правильно доработанными action-ами). Осталось засунуть ещё буквально в пару мест, типа того же CloseQuery, соответствующую проверку - и вуаля.
...
Рейтинг: 0 / 0
waitFor в потоке
    #39931503
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer
Для отсутствия таких проблем стоит пользоваться action-ами (особенно - правильно доработанными action-ами). Осталось засунуть ещё буквально в пару мест, типа того же CloseQuery, соответствующую проверку - и вуаля.

C ними не очень знаком, всегда воспринимал их как просто контейнер для обработчиков, ну и способ привязать несколько источников к одному обработчику. Как они помогут избежать нежелательного повторного вызова? Разве что дизейблить экшен внутри обработчика...
...
Рейтинг: 0 / 0
waitFor в потоке
    #39931521
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer > особенно - правильно доработанными action-ами

А что конкретно ты там патчил?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
waitFor в потоке
    #39931608
vavan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2
всегда воспринимал их как просто контейнер для обработчиков
контейнеры это actionlist/actionmanager, а сами экшны это произвольной сложности функционал, возможность кучу однотипного кода выкинуть в либу а параметры обработки задавать любимым способом в дизайнере
...
Рейтинг: 0 / 0
waitFor в потоке
    #39931637
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док
DmSer
из-за него слишком уж много граблей

Я список этих граблей давно с фонарем ищу. Можешь перечислить? :)


Одна из недавно обнаруженных проблем, которая возникает из-за Application.ProcessMessages: используем технологию DataSnap, компонент TSocketConnection. Оказалось, что если DCOM-сервер находится не в локальной сети, а через интернет, то Application.ProcessMessages входит в бесконечный цикл и не возвращает управление.

Вот процедура WaitCmd, в которой бесконечно выполняется Application.ProcessMessages:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
procedure WaitCmd();
begin
  WaitForm.Show;
  while not FThread.IsReady do
  begin
    Application.ProcessMessages;
    Sleep(10);
  end;
  WaitForm.Hide;
  if FThread.IsError then
    raise Exception.Create(FThread.FError + ' ');
end;




Поток FThread отвечает за формирование отчёта (через отдельное подключение TSocketConnection, которое создаётся в потоке). Поток тупо вызывает функцию AppServer.CreateReport(...) у TSocketConnection и выставляет флаг IsReady и запоминает результат (отчёт).
На форме WaitForm таймер, который несколько раз в секунду обращается к DCOM-серверу через подключение TSocketConnection, созданное в главном потоке и двигает ProgressBar.

Для формирования отчёта главный поток вызывает функцию GetReport:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
function GetReport(Params: Variant): string;
begin
    FThread.Params := Params;
    FThread.IsReady := false;
    WaitCmd();
    Result := FThread.FReport;
end;
...
Рейтинг: 0 / 0
waitFor в потоке
    #39931676
vavan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
компонент TSocketConnection
как этим вообще умудряются пользоваться, не пойму. я после первых же экспериментов вынужден был этот макет переписать на собственный TVSocketConnection с уникальными в чем-то фичами. может конечно после 2007 его круто поправили, не видел
...
Рейтинг: 0 / 0
waitFor в потоке
    #39931685
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vavan
DmSer
компонент TSocketConnection
как этим вообще умудряются пользоваться, не пойму. я после первых же экспериментов вынужден был этот макет переписать на собственный TVSocketConnection с уникальными в чем-то фичами. может конечно после 2007 его круто поправили, не видел


Мы очень много времени потратили на исправление различных багов в модуле SConnect.pas. Но в итоге мы своего добились - оно заработало.
...
Рейтинг: 0 / 0
waitFor в потоке
    #39931698
vavan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
Мы очень много времени потратили на исправление различных багов в модуле SConnect.pas
да уж, у меня в итоге раза в два больше юнит получился
...
Рейтинг: 0 / 0
waitFor в потоке
    #39931707
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
procedure WaitCmd();
begin
  WaitForm.Show;
  while not FThread.IsReady do
  begin
    Application.ProcessMessages;
    Sleep(10);
  end;
  WaitForm.Hide;
  if FThread.IsError then
    raise Exception.Create(FThread.FError + ' ');
end;



А не легче WaitForm.ShowModal, а по таймеру if FThread.IsReady then ModalResult := mrOK?
...
Рейтинг: 0 / 0
waitFor в потоке
    #39931762
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)
YuRock
пропущено...
Это понятно. Иначе execute не закончится.
Вопрос, что будет, если waitfor уже вызван в оконном потоке, а еще не все synchronize-вызовы обработалист в execute.
Ответ - будет дедлок.
не будет, см реализацию, там специальная затычка на главный поток
она обрабатывает появившиеся synchronize и сообщения
Да, посмотрел, действительно, в WaitFor для главного потока (в моей версии дельфей) в цикле вызывается CheckSynchronize, пока execute не закончится.
Что грузит ядро на 100% - тоже красиво.
...
Рейтинг: 0 / 0
waitFor в потоке
    #39931818
DmSer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2
DmSer

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
procedure WaitCmd();
begin
  WaitForm.Show;
  while not FThread.IsReady do
  begin
    Application.ProcessMessages;
    Sleep(10);
  end;
  WaitForm.Hide;
  if FThread.IsError then
    raise Exception.Create(FThread.FError + ' ');
end;



А не легче WaitForm.ShowModal, а по таймеру if FThread.IsReady then ModalResult := mrOK?


В итоге так и пришлось сделать :)
...
Рейтинг: 0 / 0
waitFor в потоке
    #39932026
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DmSer
В итоге так и пришлось сделать :)

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


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