TThread с обычным поведением OnTerminate

Я читал этот пост, который почти решил мою проблему, так как никто не ответил на мои комментарии, я решил задать вопрос:

Исходный пост, который почти отвечает на мой вопрос

Как я там спросил:

  • Поскольку возможно, что несколько потоков используют одно и то же событие OnTerminate, возможно ли, что они завершатся одновременно?
  • Если да, то что происходит? Вызов метода OnTerminate будет "поставлен в очередь" операционной системой? Другими словами, будет ли код свободен от повторного входа, если он использует MainThread свойства?

person EProgrammerNotFound    schedule 25.07.2013    source источник


Ответы (2)


Возможно, несколько потоков используют одно и то же событие OnTerminate.

Да, как показал вам ответ на другой вопрос.

и закончить одновременно?

Потоки могут завершить свою работу одновременно, но по умолчанию обработчики событий OnTerminate не будут вызываться одновременно. Это связано с тем, что обработчик события OnTerminate запускается TThread с помощью внутреннего вызова TThread.Synchronize(), поэтому несколько потоков, запускающих свои события OnTerminate одновременно, не будут перекрывать друг друга. Чтобы изменить это поведение (чего не делает большинство людей), вам придется переопределить виртуальный метод TThread.DoTerminate(), чтобы вручную вызывать обработчик событий OnTerminate напрямую, не вызывая сначала TThread.Synchronize().

person Remy Lebeau    schedule 25.07.2013
comment
Нет, нет, я не буду переопределять, такое поведение нормально - person EProgrammerNotFound; 25.07.2013
comment
@MartinJames Я приму ответ Реми, потому что он ответил первым и объяснил synchronize поведение, хорошо? ваш ответ был очень ясным и полезным тоже. Спасибо, ребята, за всю оказанную помощь, спасибо @Martin за подсказку Application.ProcessMessages - person EProgrammerNotFound; 25.07.2013

OnTerminate — это событие, запускаемое в потоке VCL, поэтому оно будет иметь статус PostMessaged или, что более вероятно, SendMessaged. В любом случае OnTerminates будет сериализован.

Тем не менее, я никогда не использовал это событие со времен D3 (когда я узнал, сколько поддержки потоков Delphi действительно «работало»).

Изменить - возможно, вы можете повторно ввести вызовы OnTerminate, вызвав в нем Application.ProcessMessages (если вы чувствуете себя особенно суицидально :).

person Martin James    schedule 25.07.2013
comment
Это событие прослушивается? - person EProgrammerNotFound; 25.07.2013
comment
В delphi 6, как сказал @Remy, вместо SendMessage используется синхронизация. - person EProgrammerNotFound; 25.07.2013
comment
you can maybe get your OnTerminate calls to reenter by calling Application.ProcessMessages Правда [+1]. - person EProgrammerNotFound; 25.07.2013
comment
Ну да и нет. Скажем так, он открыт для злоупотреблений. TThread.Synchronize (метод Delphi, оборачивающий межпотоковые связи ОС, необходимые для его работы) был несколько раз переработан. Обычно мне удается избежать TThread.OnTerminate, никогда явно не прерывая TThreads. - person Martin James; 25.07.2013
comment
Хм, не могли бы вы привести пример неправильного использования для дальнейшего использования? - person EProgrammerNotFound; 25.07.2013
comment
@MatheusFreitas да, и TThread.Synchronize использует либо SendMessage, либо APC в очереди. - person Martin James; 25.07.2013
comment
@MatheusFreitas: TThread всегда использовал Synchronize() для вызова обработчика событий OnTerminate. В Delphi 5 и более ранних версиях Synchronize() просто использовал SendMessage(). В Delphi 6 (когда был представлен Kylix) Synchronize() был переписан, чтобы вместо этого использовать глобальный список указателей на методы, а затем использовал PostMessage() для пробуждения основного потока. Основной поток периодически вызывает CheckSynchronize() для циклического просмотра этого списка, вызывая ожидающие методы. - person Remy Lebeau; 25.07.2013
comment
Ну, единственная проблема, которую я вижу, это если пользователь не проверяет завершение в контексте выполнения, а также если он приостанавливает и освобождает поток, но, как вы сказали, это неправильное использование, я никогда не буду этого делать. Большое спасибо - person EProgrammerNotFound; 25.07.2013