Можно ли продвинуть тупиковый поток? застрял в WaitForSingleObject

Если у меня есть приложение, которое создает потоки, которые выполняют свою работу, а затем выходят, и один или несколько потоков попадают в тупик (возможно, не по моей вине!), Есть ли способ программно заставить один из потоков продвинуться мимо WaitForSingleObject, в котором он мог застрять, и, таким образом, разрешить тупик?

Я не обязательно хочу прерывать поток, я просто хочу, чтобы он продолжил работу (и, таким образом, разрешил потокам завершиться «изящно».

(да, я знаю, что это похоже на дубликат моего предыдущего вопроса Delphi 2006 - Какой лучший способ изящно убить поток и по-прежнему активировать обработчик OnTerminate?, но ситуация немного иная - я спрашиваю здесь в том, можно ли заставить WaitForSingleObject (Handle, INFINTE) вести себя как WaitForSingleObject (Handle, ItCantPossiblyBeWorkingProperlyAfterThisLong)).

Пожалуйста, будь со мной нежнее.

* ПОДРОБНЕЕ *

Проблема не обязательно в коде, исходный код которого у меня есть. Фактическая ситуация - это библиотека последовательного COM-порта (AsyncFree), основанная на потоках. Когда порт основан на USB, кажется, что библиотека находится в тупике между двумя потоками, которые она создает при закрытии порта. Я уже подробно обсуждал это на этом форуме. Я действительно перекодировал один из вызовов WaitForSingleObject, чтобы он не был бесконечным, и это вылечило эту тупиковую ситуацию, но затем другой вызов появился позже в последовательности завершения потока, на этот раз в подпрограмме Delphi TThread.Destroy.

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


person rossmcm    schedule 18.12.2011    source источник
comment
Почему бы вам просто не изменить вызов WaitForSingleObject на not быть бесконечным?   -  person Jon Skeet    schedule 18.12.2011
comment
Исправить тупик. Исправьте болезнь.   -  person David Heffernan    schedule 18.12.2011
comment
Я не могу понять ситуацию, когда поток попадает в тупик, и вы можете заставить его перейти к другому коду за пределами тупика и, таким образом, выйти из тупика. Я считаю, что вам нужно избегать тупика, это единственная возможность ...   -  person Andreas    schedule 18.12.2011
comment
@Jon Хотя ожидание и вернулось бы, это вряд ли решило бы проблему.   -  person David Heffernan    schedule 18.12.2011
comment
@DavidHeffernan: Действительно, решение тупиковой ситуации, безусловно, было бы лучшим вариантом. На самом деле это был просто ответ на вопрос, как заставить его действовать так, как если бы я пропустил часть тайм-аута - где очевидный ответ - пройти тайм-аут :) Трудно действительно дать хороший ответ, не зная больше контекста здесь ...   -  person Jon Skeet    schedule 18.12.2011
comment
@Jon, взаимоблокировки - это самая легкая проблема многопоточности. Когда есть правильный стек потоков, он становится тривиальным при условии, что у вас есть контроль над исходным кодом.   -  person bestsss    schedule 18.12.2011
comment
Из вашего редактирования может показаться, что у вас есть исходный код. Я призываю вас выйти из тупика.   -  person David Heffernan    schedule 18.12.2011
comment
@ Дэвид, я действительно собираюсь решить эту проблему. Я хочу отступить, когда произойдет что-то, о чем я не знаю. Для меня это почти та же философия, что и обработка исключений в моих приложениях. Это там для ошибок времени выполнения, о которых я не знаю. Те, о которых я знаю, больше не происходят (надеюсь).   -  person rossmcm    schedule 18.12.2011
comment
На мой взгляд, отката нет. Тупик - это игра.   -  person David Heffernan    schedule 18.12.2011
comment
@bestsss: Это зависит от того, является ли тупик реальным тупиком, или это действительно используется здесь как сокращение для того, что что-то не завершается, и я не знаю почему.   -  person Jon Skeet    schedule 19.12.2011
comment
@Jon, Судя по моему чтению стеков трассировки, это тупик.   -  person rossmcm    schedule 19.12.2011


Ответы (2)


Вы можете сделать дескриптор, используемый в WaitForSingleObject, недействительным, закрыв его (из другого потока). В этом случае WaitForSingleObject должен вернуть WAIT_FAILED, и ваш поток будет "перемещен дальше"

person kludg    schedule 18.12.2011
comment
Спасибо @Serg. Я попробую. - person rossmcm; 18.12.2011
comment
Гениально. Страшно, но гениально. :-) - person Harry Johnston; 02.06.2017

Если вы не используете INFINITE, а просто устанавливаете заданное время ожидания, вы можете проверить, вернулся ли вызов из-за истечения времени ожидания или из-за того, что дескриптор, которого вы ждали, перешел в сигнальное состояние. Затем ваш код может решить, что делать дальше. Войдите в другой цикл ожидания или просто выйдите в любом случае, возможно, где-то будет показано «эй, я ждал, но это было слишком долго, и я все равно прервал». Другой вариант - использовать WaitForMultipleObjects и использовать что-то похожее на событие для прекращения ожидания, если это необходимо. Преимущество в том, что не нужно истекать тайм-аут. Конечно, когда поток пробуждается, он должен быть в состоянии обработать «исключительное» условие продолжения, даже если «основной» дескриптор, которого он ждал, не вернулся вовремя.

person Community    schedule 18.12.2011