Теми и събиране на боклук

Имам услуга на 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