Потоки и сборка мусора

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

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

Есть ли альтернативный способ проверить наличие/состояние пользовательских потоков? Я думал, что может быть что-то вроде следующего, используя 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. Любые идеи о том, как правильно это сделать?


person Phillip Schmidt    schedule 27.06.2012    source источник
comment
Самый простой способ убедиться, что ваши потоки очищены, — просто убедиться, что их работа в конечном итоге завершается (успешно или нет). Меня интересуют обстоятельства, при которых может быть создан поток, и вы хотели бы очистить его до завершения работы.   -  person Chris Shain    schedule 27.06.2012
comment
В любом случае прерывание темы - очень плохая идея. Обычно это срабатывает, но здесь вы встроили бомбу замедленного действия.   -  person Henk Holterman    schedule 27.06.2012


Ответы (2)


Является ли myThread переменной метода? или...?

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

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

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

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

person Marc Gravell    schedule 27.06.2012
comment
Чтобы добавить немного больше к ответу Марка, вы можете увидеть Task<T> класс. Он поддерживает отмену (если я прав из .NET 3.5) и отчет о проделанной работе (если я прав из .NET 4.5). - person oleksii; 28.06.2012
comment
@oleksii действительно, но отмена - это не то же самое, что произвольное прерывание; чтобы отмена работала правильно, сам код должен быть отменяемым - person Marc Gravell; 28.06.2012

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

person Sergei B.    schedule 27.06.2012
comment
Но мне нравится, чтобы у моих колес было четыре стороны! - person binki; 13.08.2014