Это на самом деле довольно запутанная тема.Одна из причин, почему мы все говорим о Thread.Abort
, заключается в том, что он внедряет асинхронное исключение в целевой поток.Инъекция является недетерминированной и часто может быть в опасной точке.Это может произойти сразу после получения ресурса (блокировка, неуправляемый ресурс и т. Д.), Что приведет к утечке ресурса или оставлению блокировки в полученном состоянии.В CLR есть некоторые положения для снижения риска путем попыток отсрочить внедрение несколькими очень сложными способами во время выполнения блоков try-catch-finally.К сожалению, не существует надежного способа гарантировать все сценарии, связанные с вызовом Thread.Abort
, и я подозреваю, что большая часть крайних случаев лежит в области неуправляемого кода.По этой причине я советую не прерывать потоки.
Вместо этого вы должны спроектировать свой плагин так, чтобы он работал в отдельном AppDomain
и принимал запросы на отключение, чтобы у него была возможность изящно завершиться самостоятельно.Был бы некоторый предельный уровень защиты при использовании отдельного домена приложения, поскольку в качестве крайней меры можно было бы прервать неправильно работающий поток, а затем удалить AppDomain
, в котором поток выполнял код.Опять же, нет никакой гарантии, что это полностью изолирует потенциал для поврежденного состояния, вызванного прерыванием.Единственный отказоустойчивый дизайн - запускать плагин в своем собственном процессе.
Вне зависимости от проблемы прерывания, есть пара вещей, которые необходимо сделать, чтобы убедиться, что неуправляемый ресурс освобожден.Во-первых, реализуйте финализатор так, чтобы при отсутствии вызова Dispose
финализатор должен был это сделать в конце концов.Во-вторых, и я не уверен, какой уровень защиты это на самом деле обеспечивает, вызовите GC.SuppressFinalize
после вызова частного Dispose(bool)
метода.Если асинхронное исключение должно было быть внедрено в публичном методе Dispose
, вы не хотите, чтобы объект был удален из очереди финализации.Опять же, я не уверен, насколько это поможет, потому что ваш объект теперь может быть в поврежденном состоянии, что помешает второй попытке освободить ресурс.В-третьих, если возможно, используйте один из классов CriticalFinalizerObject
или SafeHandle
, чтобы обернуть ресурс, поскольку это добавляет дополнительную защиту за счет использования Области ограниченного выполнения .