Надлежащий способ уничтожить объект TThread

Этот вопрос может казаться тривиальным, но я надеюсь, что Вы не проигнорируете его.
Прежде, чем уничтожить TThread возражают, что обычно необходимо ожидать до потока который названный TThread. Выполнитесь (), концы метода, для только затем могут мы быть уверенными, что, например, к объектам, уничтоженным в деструкторе класса, больше не получают доступ. Поэтому необходимо назвать Оконечным для установки флага Terminated, который поток должен проверить, чтобы знать, выйти ли или не и затем назвать WaitFor () методом.

Поскольку поток может быть приостановлен, я думаю, что хорошо возобновить его прежде, чем назвать WaitFor, поскольку иначе вызывающий поток был бы заведен в тупик. И потому что поток может быть приостановлен многократно, он должен быть возобновлен то же количество раз, правильно?

while Suspended do
  Resume;

Если бы поток был создан приостановленный, то мы не должны волноваться что TThread. Выполнитесь (), метод назовут, когда мы возобновим поток только для завершения его - он не будет (исправьте меня, если я неправ).

То, что я заявил, предлагает использовать следующие строки кода для каждого освобождаемого объекта TThread:

MyThread.Terminate;
while MyThread.Suspended do
  MyThread.Resume;
MyThread.WaitFor;
MyThread.Free;

К сожалению, когда мы уничтожаем наше приложение, которое создало несколько потоков, пишущий, что такая часть кода для каждого объекта TThread, уничтожаемого излишне, делает код очень долго и возможно даже непрозрачный.

Поэтому я пришел к выводу, что все, они могли быть помещены в переопределенном деструкторе класса TThread, благодаря которому будет достаточно назвать MyThread. Свободный (или MyThread. Оконечный, если MyThread. FreeOnTerminate установлен), не заботясь о том, является ли уничтоженный объект объектом TThread или нет:

destructor TMyThread.Destroy;
begin
  //if FreeOnTerminate, the calling thread cannot wait for itself
  if GetCurrentThreadId <> ThreadId then
  begin
    Terminate;
    while Suspended do
      Resume;
    WaitFor;
  end;

  {free all objects created in this class}

  inherited Destroy;
end;

Простите мне задающий такой основной вопрос. Я хотел бы, однако, узнать Ваши мнения об этом пути - я надеюсь что универсальный путь - уничтожения объектов TThread. Я задаю этому вопросы, поскольку я узнал из кодов своих коллег, что они обычно использовали первый пример кода для уничтожения таких объектов, но они никогда раньше не проверяли, не были ли потоки, ожидающий для, приостановлены, который я считал немного опасным, если потоки могли бы быть приостановлены где-нибудь в коде. Поэтому я пытался найти универсальный способ уничтожить объекты этого класса, который сделает код более четким и более безопасным. Я надеюсь, что не сделал это хуже - что Вы думаете?

Спасибо за Ваши предложения заранее.

16
задан Mariusz Schimke 6 July 2009 в 22:32
поделиться

2 ответа

Much of what your suggesting is already performed in the TThread.Destroy destructor, and invoking TMyThread.free will do just what your suggesting. To cleanup any objects owned by the thread class, you can perform that in the OnTerminate event, which will get invoked as part of the thread shutdown logic.

8
ответ дан 30 November 2019 в 22:43
поделиться

Не существует универсального способа остановить поток, так же как нет универсального способа (изящно) остановить процесс. Каждый из них отличается.

Для некоторых потоков достаточно установить его свойство Завершено с помощью метода Завершить . Однако другие потоки вызывают такие функции, как GetMessage или MsgWaitForMultipleObjects , которые будут блокироваться до тех пор, пока что-то не произойдет, например, не будет получено сообщение или дескриптор ядра не получит сигнал. TThread.Terminate не может сделать что-либо из этого, поэтому он не может остановить эти потоки. Когда я писал подобные потоки, я предоставлял свои собственные функции для уведомления их о прекращении работы. Я мог бы вызвать PostThreadMessage , чтобы передать сообщение в поток » s, или я мог бы сигнализировать о событии, которое класс потока предоставил для уведомления его о запросе на завершение.

Не беспокойтесь о возобновлении приостановленного потока. Вы действительно не должны их приостанавливать. Единственный безопасный способ приостановить поток - это приостановить его, и как только вы это сделаете, вы гарантированно получите как минимум два потока, контролирующих его выполнение: сам поток, который его приостанавливает, и хотя бы один другой. поток, чтобы возобновить его снова. Поток должен контролировать свое выполнение.

Было бы здорово, если бы TThread.Terminate был виртуальным. Тогда каждый класс потока может предоставить собственный способ уведомить себя о том, что он должен прекратить работу. Некоторые могут просто установить Terminated , а другие могут публиковать сообщения, сигнальные события или делать все, что им нужно. Однако на самом деле невиртуальный метод плохо работает с потоками, которые проводят много времени в ожидании других вещей. Текущий способ работает только для потоков, которые могут часто опрашивать свои Завершенные свойства.

У некоторых потоков установлены свойства FreeOnTerminate . Для этих потоков ваш код небезопасен. С технической точки зрения, вызывать какие-либо методы для таких объектов небезопасно, поскольку поток может завершиться в любой момент. Но даже если вы знаете, что поток все еще работает, а объект потока все еще существует, объект определенно перестанет существовать через некоторое время после вызова Terminate . Вы не можете вызвать WaitFor для объекта потока, работающего бесплатно при завершении, и вы определенно не можете вызвать Free .

тем не менее, невиртуальный метод плохо работает с потоками, которые проводят много времени в ожидании других вещей. Текущий способ работает только для потоков, которые могут часто опрашивать свои Завершенные свойства.

У некоторых потоков установлены свойства FreeOnTerminate . Для этих потоков ваш код небезопасен. С технической точки зрения, вызывать какие-либо методы для таких объектов небезопасно, поскольку поток может завершиться в любой момент. Но даже если вы знаете, что поток все еще работает, а объект потока все еще существует, объект определенно перестанет существовать через некоторое время после вызова Terminate . Вы не можете вызвать WaitFor для объекта потока, работающего бесплатно при завершении, и вы определенно не можете вызвать Free .

тем не менее, невиртуальный метод плохо работает с потоками, которые проводят много времени в ожидании других вещей. Текущий способ работает только для потоков, которые могут часто опрашивать свои Завершенные свойства.

У некоторых потоков установлены свойства FreeOnTerminate . Для этих потоков ваш код небезопасен. С технической точки зрения, вызывать какие-либо методы для таких объектов небезопасно, поскольку поток может завершиться в любой момент. Но даже если вы знаете, что поток все еще работает, а объект потока все еще существует, объект определенно перестанет существовать через некоторое время после вызова Terminate . Вы не можете вызвать WaitFor для объекта потока, работающего бесплатно при завершении, и вы определенно не можете вызвать Free .

невиртуальный метод плохо работает с потоками, которые проводят много времени в ожидании других вещей. Текущий способ работает только для потоков, которые могут часто опрашивать свои Завершенные свойства.

У некоторых потоков установлены свойства FreeOnTerminate . Для этих потоков ваш код небезопасен. С технической точки зрения, вызывать какие-либо методы для таких объектов небезопасно, поскольку поток может завершиться в любой момент. Но даже если вы знаете, что поток все еще работает, а объект потока все еще существует, объект определенно перестанет существовать через некоторое время после вызова Terminate . Вы не можете вызвать WaitFor для объекта потока, работающего бесплатно при завершении, и вы определенно не можете вызвать Free .

невиртуальный метод плохо работает с потоками, которые проводят много времени в ожидании других вещей. Текущий способ работает только для потоков, которые могут часто опрашивать свои Завершенные свойства.

У некоторых потоков установлены свойства FreeOnTerminate . Для этих потоков ваш код небезопасен. С технической точки зрения, вызывать какие-либо методы для таких объектов небезопасно, поскольку поток может завершиться в любой момент. Но даже если вы знаете, что поток все еще работает, а объект потока все еще существует, объект определенно перестанет существовать через некоторое время после вызова Terminate . Вы не можете вызвать WaitFor для объекта потока, работающего бесплатно при завершении, и вы определенно не можете вызвать Free .

t хорошо работают с потоками, которые проводят много времени в ожидании других дел. Текущий способ работает только для потоков, которые могут часто опрашивать свои Завершенные свойства.

У некоторых потоков установлены свойства FreeOnTerminate . Для этих потоков ваш код небезопасен. С технической точки зрения, вызывать какие-либо методы для таких объектов небезопасно, поскольку поток может завершиться в любой момент. Но даже если вы знаете, что поток все еще работает, а объект потока все еще существует, объект определенно перестанет существовать через некоторое время после вызова Terminate . Вы не можете вызвать WaitFor для объекта потока, работающего бесплатно при завершении, и вы определенно не можете вызвать Free .

t хорошо работают с потоками, которые проводят много времени в ожидании других дел. Текущий способ работает только для потоков, которые могут часто опрашивать свои Завершенные свойства.

У некоторых потоков установлены свойства FreeOnTerminate . Для этих потоков ваш код небезопасен. С технической точки зрения, вызывать какие-либо методы для таких объектов небезопасно, поскольку поток может завершиться в любой момент. Но даже если вы знаете, что поток все еще работает, а объект потока все еще существует, объект определенно перестанет существовать через некоторое время после вызова Terminate . Вы не можете вызвать WaitFor для объекта потока, работающего бесплатно при завершении, и вы определенно не можете вызвать Free .

Текущий способ работает только для потоков, которые могут часто опрашивать свои Завершенные свойства.

У некоторых потоков установлены свойства FreeOnTerminate . Для этих потоков ваш код небезопасен. С технической точки зрения, вызывать какие-либо методы для таких объектов небезопасно, поскольку поток может завершиться в любой момент. Но даже если вы знаете, что поток все еще работает, а объект потока все еще существует, объект определенно перестанет существовать через некоторое время после вызова Terminate . Вы не можете вызвать WaitFor для объекта потока, работающего бесплатно при завершении, и вы определенно не можете вызвать Free .

Текущий способ работает только для потоков, которые могут часто опрашивать свои Завершенные свойства.

У некоторых потоков установлены свойства FreeOnTerminate . Для этих потоков ваш код небезопасен. С технической точки зрения, вызывать какие-либо методы для таких объектов небезопасно, поскольку поток может завершиться в любой момент. Но даже если вы знаете, что поток все еще работает, а объект потока все еще существует, объект определенно перестанет существовать через некоторое время после вызова Terminate . Вы не можете вызвать WaitFor для объекта потока, работающего бесплатно при завершении, и вы определенно не можете вызвать Free .

Для некоторых потоков установлены свойства FreeOnTerminate . Для этих потоков ваш код небезопасен. С технической точки зрения, вызывать какие-либо методы для таких объектов небезопасно, поскольку поток может завершиться в любой момент. Но даже если вы знаете, что поток все еще работает, а объект потока все еще существует, объект определенно перестанет существовать через некоторое время после вызова Terminate . Вы не можете вызвать WaitFor для объекта потока, работающего бесплатно при завершении, и вы определенно не можете вызвать Free .

Для некоторых потоков установлены свойства FreeOnTerminate . Для этих потоков ваш код небезопасен. С технической точки зрения, вызывать какие-либо методы для таких объектов небезопасно, поскольку поток может завершиться в любой момент. Но даже если вы знаете, что поток все еще работает, а объект потока все еще существует, объект определенно перестанет существовать через некоторое время после вызова Terminate . Вы не можете вызвать WaitFor для объекта потока, работающего бесплатно при завершении, и вы определенно не можете вызвать Free .

Но даже если вы знаете, что поток все еще работает, а объект потока все еще существует, объект определенно перестанет существовать через некоторое время после вызова Terminate . Вы не можете вызвать WaitFor для объекта потока, работающего бесплатно при завершении, и вы определенно не можете вызвать Free .

Но даже если вы знаете, что поток все еще работает, а объект потока все еще существует, объект определенно перестанет существовать через некоторое время после вызова Terminate . Вы не можете вызвать WaitFor для объекта потока, работающего бесплатно при завершении, и вы определенно не можете вызвать Free .

8
ответ дан 30 November 2019 в 22:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: