На высоком уровне я бы просто предложил использовать пул потоков .NET (System.Threading.ThreadPool
) для постановки в очередь и выполнения нескольких рабочих элементов, поскольку это то, для чего он был разработан (предполагая, что рабочие элементы разрешено выполнять асинхронно). В частности, проверьте метод QueueUserWorkItem
.
Чтобы ответить на ваши вопросы, хотя:
Должен ли я поместить код деструктора C ++ в:
Пользовательский метод CleanUp (), который клиент должен вызывать при выходе из приложения? Что если клиент забудет?
Метод Dispose () для IDisposable, чтобы клиент также мог его вызывать? Но опять же, что, если клиент забудет?
Всегда предпочитайте реализацию IDisposable
по сравнению с пользовательскими CleanUp
методами (в BCL некоторые классы Stream
имеют метод Close
, который на самом деле является просто псевдонимом для Dispose
). Шаблон IDisposable
- это способ выполнить детерминированную очистку с помощью C #. Клиент, забывший вызвать Dispose
, всегда является проблемой, но это часто можно обнаружить с помощью инструментов статического анализа (например, FxCop).
Внутри метода финализатора C #, чтобы он всегда выполнялся? Я читал, что если у вас нет неуправляемых ресурсов, вы не должны включать метод финализатора, потому что это снижает производительность.
Финализаторам не гарантируется выполнение (см. эту статью ), поэтому правильная программа не может предполагать, что они будут выполняться. Производительность не будет проблемой здесь. Я предполагаю, что у вас будет максимум пара MessagePump
объектов, поэтому стоимость наличия финализатора незначительна.
Nowhere? Просто игнорируйте пометку флага done_ и просто позвольте GC обработать его естественным образом, поскольку объект Thread является управляемым ресурсом? Будет ли поток принудительно прерван таким образом?
Поток управляется CLR и будет должным образом очищен. Если поток возвращается из своей точки входа (Run
здесь), он не будет прерван, он просто выйдет чисто. Этот код все еще должен куда-то идти, поэтому я бы обеспечил явную очистку через IDisposable
.
Я также обнаружил, что если я не отмечу поток рассылки сообщений, созданный внутри конструктора, как фоновый поток, мой объект MessagePump никогда не получит GC, и приложение просто зависнет при выходе. В чем причина?
Приложение .NET работает до тех пор, пока не прекратятся все потоки переднего плана (не фоновые). Поэтому, если вы не пометите свой поток MessagePump
как фоновый поток, он будет поддерживать ваше приложение во время его работы. Если какой-то объект все еще ссылается на ваш MessagePump
, то MessagePump
никогда не будет GC'едирован или завершен. Снова ссылаясь на статью выше, вы не можете предполагать, что финализатор когда-либо будет работать.