Отменить вызов неуправляемой библиотеки DLL
У меня есть неуправляемая DLL с функцией, которая может работать в течение длительного времени, если входной параметр является большим значением, иногда это желательно, но не всегда.
Как я могу в С# вызвать эту функцию, чтобы я мог ее прервать при необходимости?
До сих пор я пытался поместить вызов в отдельный поток, но ни прерывание, ни прерывание, похоже, не прекратили процесс, который работает на 100% CPU до тех пор, пока dll не будет завершено.
Возможно ли завершить работу кода dll?
Ответы
Ответ 1
Неуправляемый код отменяется только в том случае, если это "аварийное состояние ожидания". Это не будет, когда он сжигает 100% циклов процессора. P/Invoking TerminateThread будет работать, предполагая, что вы можете получить дескриптор потока, который .NET очень затрудняет. В любом случае это не поможет, вы будете утечка стека потоков. На одном мегабайте вы быстро исчерпаете виртуальную память. Даже если это только случайная потребность, вы все еще можете столкнуться с серьезными проблемами, поскольку поток имеет мутированное глобальное состояние программы, и вы не знаете, как его восстановить.
Единственный хороший способ прервать неуправляемый код - запустить его в отдельном процессе и запустить его в голову с помощью Process.Kill(). Операционная система очистит шрапнель. Вам нужно будет написать небольшую программу хостинга для DLL и использовать один из средств взаимодействия между процессами, чтобы поговорить с ним. Сокеты, именованные каналы, удаленное взаимодействие .NET, WCF, выбирают.
Ответ 2
Из MSDN
Если Abort вызывается в управляемом потоке в то время как он выполняет неуправляемый код, исключение ThreadAbortException не выбрасывается пока поток не вернется к управляемому код.
Итак, кажется, прерывание управляемого потока невозможно.
В качестве альтернативы вы можете попробовать запустить неуправляемый поток с помощью API Win32 CreateThread()
, WaitForSingleObject()
и TerminateThread()
. Используйте подписи здесь.
Я не пробовал это сам, но он, безусловно, вводит некоторые риски, так как вы не можете определить, в какой момент исполнения вы убиваете поток. Это может также привести к утечке ресурсов. MSDN перечисляет некоторые побочные эффекты в справочнике TerminateThread()
.
В общем, я бы посоветовал против такого прерывания. Возможно, у вас есть возможность изменить неуправляемую DLL, чтобы обеспечить изящную отмену.