Утилизация предметов внутри резьбы - PullRequest
2 голосов
/ 22 сентября 2010

Я программирую плагин для большой системы.Система запускает мой плагин в независимой ветке.Внутри плагина я выделяю неуправляемый ресурс.Я должен быть уверен на 100%, что я выпущу этот драйвер.Я реализовал шаблон IDisposable и рассмотрел все методы, которые система называет вызывающими, если плагин собирается завершить работу.

Я немного волнуюсь из-за ситуации, когда система по какой-либо причине выходит из моего потока (Прервать или что-то еще).Могу ли я сделать что-то еще в своем плагине, чтобы обеспечить освобождение неуправляемого ресурса?

Например, если я нажимаю Stop-отладку в VS, ресурс остается невыпущенным (я знаю, что это глупый пример).

Ответы [ 4 ]

1 голос
/ 22 сентября 2010

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

Вместо этого вы должны спроектировать свой плагин так, чтобы он работал в отдельном AppDomain и принимал запросы на отключение, чтобы у него была возможность изящно завершиться самостоятельно.Был бы некоторый предельный уровень защиты при использовании отдельного домена приложения, поскольку в качестве крайней меры можно было бы прервать неправильно работающий поток, а затем удалить AppDomain, в котором поток выполнял код.Опять же, нет никакой гарантии, что это полностью изолирует потенциал для поврежденного состояния, вызванного прерыванием.Единственный отказоустойчивый дизайн - запускать плагин в своем собственном процессе.

Вне зависимости от проблемы прерывания, есть пара вещей, которые необходимо сделать, чтобы убедиться, что неуправляемый ресурс освобожден.Во-первых, реализуйте финализатор так, чтобы при отсутствии вызова Dispose финализатор должен был это сделать в конце концов.Во-вторых, и я не уверен, какой уровень защиты это на самом деле обеспечивает, вызовите GC.SuppressFinalize после вызова частного Dispose(bool) метода.Если асинхронное исключение должно было быть внедрено в публичном методе Dispose, вы не хотите, чтобы объект был удален из очереди финализации.Опять же, я не уверен, насколько это поможет, потому что ваш объект теперь может быть в поврежденном состоянии, что помешает второй попытке освободить ресурс.В-третьих, если возможно, используйте один из классов CriticalFinalizerObject или SafeHandle, чтобы обернуть ресурс, поскольку это добавляет дополнительную защиту за счет использования Области ограниченного выполнения .

1 голос
/ 22 сентября 2010

Вам необходимо реализовать оба финализатора и IDisposable, чтобы, если по какой-либо причине Dispose не вызывался (прерывание потока), GC освободил бы его.

Итак, ваш финализатор вызовет ваш метод Dispose:

class MyClass : IDisposable
{
    public void Dispose()
    {
        Dispose(true);
    }

    private void Dispose(bool disposing)
    {
        // release ...
    }

    ~MyClass()
    {
        Dispose(false);
    }
}

Причиной прохождения утилизации является то, что вы знаете, что не трогаете ни одно состояние, если оно завершается.

1 голос
/ 22 сентября 2010

Попробуйте перехватить это исключение: http://msdn.microsoft.com/en-us/library/system.threading.threadabortexception.aspx

И сделать там утилизацию, если ресурс не был утилизирован.

1 голос
/ 22 сентября 2010

В .NET невозможно запустить код, когда поток завершается. Лучшее, что вы можете сделать, это написать финализатор и надеяться, что его вызовут в разумные сроки.

...