Как прекратить долго выполнять темы изящно? - PullRequest
5 голосов
/ 01 ноября 2008

У меня проблема с многопоточностью в Delphi. Я думаю, что это распространено и в других языках. У меня есть длинный процесс, который я делаю в потоке, который заполняет список в главном окне. Но если некоторые параметры меняются в это время, то я должен прекратить выполнение текущего потока и начать с начала. Delphi предлагает завершить поток, установив Termination: = true и проверив значение этой переменной в потоке. Однако моя проблема заключается в том, что долго выполняющаяся часть скрывается в вызове библиотеки, и в этом вызове я не могу проверить переменную Termination. Поэтому мне пришлось ждать завершения этого вызова библиотеки, что влияет на всю программу.

Какой предпочтительный способ сделать в этом случае? Могу ли я немедленно убить тему?

Ответы [ 4 ]

9 голосов
/ 01 ноября 2008

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

Поскольку вы не можете изменить код, вы не можете этого сделать; вам либо придется жить с фоновой операцией (но вы можете отсоединить ее от любого пользовательского интерфейса, чтобы ее завершение было проигнорировано); или, альтернативно, вы можете попытаться прекратить его (TerminateThread API грубо прекратит работу любого потока, учитывая его дескриптор). Прекращение не является чистым, хотя, как говорит Роб, любые блокировки, удерживаемые потоком, будут отменены, и любое состояние перекрестного потока, защищенное такими блокировками, может быть повреждено.

Можете ли вы назвать вызов функции в отдельном исполняемом файле? Возможно, используя RPC (каналы, TCP, а не разделяемую память из-за той же проблемы блокировки), чтобы вы могли завершить процесс, а не завершить поток? Изоляция процесса даст вам гораздо больше защиты. Пока вы не полагаетесь на кросс-процессные именованные вещи, такие как мьютексы, это должно быть намного безопаснее, чем уничтожение потока.

3 голосов
/ 01 ноября 2008

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

3 голосов
/ 01 ноября 2008

Потоки должны взаимодействовать для достижения плавного отключения. Я не уверен, предлагает ли Delphi механизм для прерывания другого потока, но такие механизмы доступны в .NET и Java, но его следует рассматривать как последний вариант, и состояние приложения после его использования остается неопределенным.

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

0 голосов
/ 04 ноября 2008

Я написал это в ответ на похожий вопрос :

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

Для завершения потока я использую QueueUserAPC, чтобы поставить в очередь вызов функция, которая выдает исключение. Тем не менее, исключение, которое выбрасывается не выводится из типа «Исключение», поэтому будет пойман только процедура обертки моей нити.

Я очень успешно использовал это с приложениями C ++ Builder. Мне не известны все тонкости обработки исключений в Delphi и C ++, но я ожидаю, что их можно легко изменить, чтобы они работали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...