Сторожевой таймер для блокировки вызова функции

У меня есть API с закрытым исходным кодом для некоторого аппаратного датчика, который я использую для запроса этого датчика. API поставляется в виде DLL, которую я использую для взаимодействия с C#. Функции API блокируются. Обычно они возвращают значения ошибок, но в некоторых случаях они просто не возвращаются.

Мне нужно иметь возможность обнаружить эту ситуацию и в этом случае убить заблокированный поток. Как это можно сделать на С#?

Поток, в котором они вызываются, создается с помощью BackgroundWorker. Я ищу простую сторожевую собаку для блокировки вызовов функций, которую я могу настроить перед вызовом функции и сбросить, когда вернусь. Он должен просто сидеть там и ждать, пока я вернусь. Если я этого не сделаю, он убьет поток, чтобы 1) API снова освободился, и ни один поток моего приложения все еще не зависал и не делал что-нибудь, если оно в конечном итоге вернется, и 2) я могу принять другие меры по восстановлению, такие как повторная инициализация API, чтобы продолжить работу с ним.


person ygoe    schedule 12.08.2011    source источник


Ответы (1)


Один из подходов может состоять в том, чтобы настроить System.Threading.Timer до того, как вызов API сработает после определенного интервала времени ожидания, а затем удалить Timer после завершения вызова. Если таймер сработает, он сработает в потоке ThreadPool, после чего вы сможете предпринять соответствующие действия, чтобы убить нарушивший поток.

Обратите внимание, что вам потребуется P/Invoke для Win32 TerminateThread API, так как .NET Thread.Abort() не будет работать, если вы заблокированы в неуправляемом коде.

Также обратите внимание, что очень маловероятно, что ваш процесс будет находиться в безопасном состоянии после принудительного уничтожения потока, так как завершенный поток может содержать объекты синхронизации, мог быть в процессе изменения состояния общей памяти или любая другая такая важная операция. В результате его завершения могут зависнуть другие потоки, может произойти сбой процесса, могут быть повреждены данные, собаки и кошки могут начать жить вместе; нет никакого способа быть уверенным, что произойдет, но есть вероятность, что это будет плохо. Самый безопасный подход, если это возможно, состоит в том, чтобы изолировать использование API в отдельном процессе, с которым вы взаимодействуете через какой-либо канал удаленного взаимодействия. Затем вы можете убить этот внешний процесс по требованию, так как уничтожение процесса намного безопаснее, чем уничтожение потока.

person Timothy Fries    schedule 12.08.2011
comment
Хороший ответ. Помимо того, что кошки и собаки живут вместе, память будет утекать, когда вы убиваете потоки. Мне нравится ваше предложение иметь отдельный процесс, который можно убить. Очистка таким образом более автоматическая. - person aaaa bbbb; 13.08.2011
comment
+1: Согласен. Отдельный процесс - лучший способ пойти. Это отстой, но так иногда бывает в жизни. - person Brian Gideon; 13.08.2011
comment
Идея отдельного процесса действительно хороша. Это также спасло бы меня от создания всего управляемого приложения для x86, потому что у меня есть только 32-разрядная версия этой неуправляемой DLL. (Просто смотрю, появятся ли еще другие идеи.) - person ygoe; 13.08.2011