2012-06-27 3 views
1

У меня есть служба Windows, которая работает непрерывно и создает некоторые потоки, чтобы выполнить некоторую работу. Я хочу убедиться, что эти потоки правильно утилизированы (мусор, собранный после их завершения.Threads and garb collection

Однако, я также хочу, чтобы у меня была возможность проверить, периодически ли они живы, и прекратить их, если они есть. Я не могу ссылаться на них, потому что тогда они не собирались собирать мусор.

Есть ли альтернативный способ проверить существование/состояние пользовательских потоков? Я думал, может быть, что-то вроде выполняется с помощью WeakReference: (я не могу полностью проверить прямо сейчас, или я просто проверить это сам)

List<WeakReference> weakReferences; 
Thread myThread = new Thread(() => Foo()); 
WeakReference wr = new WeakReference(myThread); 
weakReferences.Add(wr); //adds a reference to the thread but still allows it to be garbage collected 
myThread.Start(); 
myThread = null; //get rid of reference so thread can be garbage collected 

, а затем в начале моего onTimeElapsed события (курсируют каждые 5 минут):

foreach(WeakReference wr in weakReferences) 
{ 
    Thread target = wr.Target as Thread; //not sure if this cast is really possible 
    if(target.IsAlive && otherLogic) 
    { 
     target.Abort(); 
    { 
} 

Но я не знаю точно, как работает WeakReference. Любые идеи о том, как правильно это сделать?

+0

Самый простой способ убедиться, что ваши потоки очищены - это просто обеспечить, чтобы их работа в конечном итоге заканчивалась (успешно или иначе). Мне интересно об обстоятельствах, в которых поток может быть порожден, и вы хотите очистить его до завершения работы. –

+2

Прекратить нить - это очень плохая идея. Обычно это работает, но вы построили бомба замедленного действия здесь. –

ответ

5

Есть myThread переменная метода? или...?

В большинстве сценариев нить будет просто собрать мусор, когда это возможно. Нет необходимости устанавливать myThread на null, если myThread - это переменная метода, потому что не существует в то время.

Я бы, однако, заметил, что потоки на самом деле довольно дорогостоящие объекты (один только стек - это боль, которую нужно выделить). Если возможно, я бы предложил либо использовать ThreadPool (если каждый элемент недолговечен), либо заказную рабочую очередь (если дольше), потенциально с несколькими рабочими, обслуживающими одну очередь.

Что касается прекращения/прерывания потока ... то есть never a хорошая идея; у вас есть нет идеи что поток делает в этой точке. После этого возможно, что весь ваш процесс обречен. Если у всех возможно, подумайте о том, что рабочий иногда проверяет флаг «прервать». Если это невозможно, рассмотрите возможность работы в отдельном процессе. Процесс еще дороже, чем поток, но он имеет то преимущество, что он изолирован; вы можете убить его, не оказывая влияния на себя. Конечно, вы все равно могли бы повредить файлы, на которых он работал, и т. Д.

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

+0

Чтобы добавить немного к ответу Марка, вы можете увидеть класс ['Task '] (http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx). Он поддерживает отмену (если я прав от .NET 3.5) и отчет о проделанной работе (если я прав из .NET 4.5). – oleksii

+0

@oleksii действительно, но аннулирование * не * равнозначно произвольному прерыванию; для отмены для правильной работы, сам код необходимо отменить –

2

Используйте пул потоков. Не создавайте нити самостоятельно и не изобретайте колесо.

+1

Но мне нравятся мои колеса с четырьмя сторонами! – binki