Это правильный способ использования OmniThreadLibrary - прекратить существующий, а затем создать новый? - PullRequest
1 голос
/ 29 марта 2012

Я использую превосходную библиотеку OmniThreadLibrary для реализации потокового анализа исходного кода, программе необходимо отказаться от существующего синтаксического анализа и перезапустить анализ всякий раз, когда изменяется исходный код.

Я делаю это с помощью фрагмента кода, показанного ниже, это правильный путь? Нужно ли мне проверять свойство Terminated потока в функции ThreadedParseHtml?

if FParserThread <> nil then
begin
  FParserThread.RemoveMonitor;
  FParserThread.Terminate(500);
end;

FParserThread := CreateTask(ThreadedParse);
FParserThread.SetParameter('SourceCode', Editor.Lines.Text);
FParserThread.MonitorWith(FParserThreadMonitor);
FParserThread.Run;

Заранее спасибо!

Редактировать 1 : Извините за повторное открытие этого вопроса, но я обнаружил утечки памяти, когда FParserThread не завершается сам по себе, вызывая метод Terminate с достаточным количеством времени ... Любые идеи относительно что может вызвать утечку памяти? Спасибо!

Редактировать 2 : прочитать эту запись в блоге , я до сих пор не могу понять, в чем может быть проблема, поскольку после каждого шага в ThreadedParse код прерывается, если Terminated Туре ...

Редактировать 3 : Отвечая на вопросы Роба:

  1. В обработчике события OnTeridity (здесь не показан) для FParserThread установлено значение «nil», поэтому под «FParser сам завершается», я имею в виду, что блок if FParserThread <> nil then не выполняется, в этом случае FParserThread завершен, потому что его разбор завершен.

  2. Логика, лежащая в основе кода, заключается в том, что, это редактор кода, при любом редактировании кода будет запускаться поток для анализа исходного кода во внутреннем древовидном представлении, в случае, когда новое редактирование кода случается, но предыдущий анализ не был отредактирован, программа сначала принудительно выполнит предыдущий поток синтаксического анализа, затем запустит новый. Это может быть не очень хороший подход ...

Редактировать 4 : Прочитав этот похожий вопрос SO , я изменил свой код на вызов FParserThread.Terminate без параметра, что означает, что, если я правильно понимаю, это утверждение будет только сигнализируя о завершении потока, и внутри самой задачи потока я применил логику для выхода из выполнения потока, если свойство Terminated равно True.

Теперь, что связано с тем, что с помощью Tracetool я обнаружил, что после вызова FParserThread.Terminate событие OnTaskMessage (где я очищаю воспоминания) больше не будет запущено, вот что вызвал утечки памяти ....

Ответы [ 2 ]

3 голосов
/ 30 марта 2012

Вам не нужно проверять свойство Terminated в связанной задаче.Вы вызываете Terminate(1), который принудительно уничтожит поток, если он не завершится в указанном вами окне в 1 мс.

Однако принудительно уничтожатьнить.Этот поток мог иметь мьютекс или критическую секцию, когда вы его убили, поэтому его уничтожение приведет к тому, что общие данные останутся в несогласованном состоянии.Это может иметь пагубные последствия для всей вашей программы.

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

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

1 голос
/ 10 июня 2014

OP здесь, после использования OmniThreadLibrary в течение более 2 лет, я пришел к выводу, что правильным способом остановки задачи OTL является использование токенов отмены. Пример кода ниже.

В потоке вызывающего абонента (обычно в основном потоке) вызовите:

//this will tell (not kill) the thread identified by myTask to stop.
myTask.CancellationToken.Signal;

В потоке вызываемого пользователя вы должны регулярно проверять свойство task.CancellationToken.IsSignaled, если оно становится истинным, завершить выполнение, и завершение потока будет обработано системой и OTL:

if task.CancellationToken.IsSignaled then
  Exit;
...