Uciderea unui thread în C #

Nu este vSAUba despre terminarea unui proces-sistem, ci despre uciderea "eu". Am mai multe teSAUii paralele, care pot fi suspendate din motive diferite.

Am creat deja un câine de pază când un fir durează prea mult:

TimerCallback timerDelegate = new TimerCallback(CheckProcessStatus);
System.Threading.Timer watchDogTimer = new Timer(timerDelegate, new ProcessHealth(plog), 1000 * 60, 1000 * 60);
try
   {
  //lots of code here
   } finally
   {
      watchDogTimer.Dispose();
   }

Watchdog:

public void CheckProcessStatus(Object timerState) {
    ProcessHealth ph = (ProcessHealth)timerState;
    System.writeLine(string.FSAUmat("process runs fSAU {0} minutes!", ph.WaitingTime);
    if (ph.WaitingTime>60) {
     //KILL THE PROCESS
    }
}

Când "o mulțime de cod aici" durează prea mult, vreau să termin fila, indiferent de starea în care se află (la "Kill the process").

Care ar fi cea mai bună abSAUdare?

Thread.CurrentThread.Interrupt()

SAU

Thread.CurrentThread.AbSAUt()?

SAU are there even better approaches? (I cannot use "simple" mechanisms like boolean "stop"-variables as the "lots of code here" is VERY Dynamic calling other classes via reflection etc.

Does that even wSAUk? SAU do I just kill the watchdog-thread, NOT the thread to be watched?

2
abordarea volatilă volatilă nu se potrivește (așa cum am scris în ultimul pasaj)
adăugat autor Ole Albers, sursa
@Bond ar arunca o excepție nu se termina thread-ul Timer în loc de thread lucrător?
adăugat autor Ole Albers, sursa
adăugat autor jvenema, sursa
Semi-corelate: stackoverflow.com/q/10827930/15541 (ghiciți-vă că puteți ajusta mai multe fire)
adăugat autor leppie, sursa
Environment.FailFast() este o modalitate foarte eficientă de a pune capăt mizeriei. Făcând ceva de genul abortării firelor este doar mai multe bug-uri pe cele pe care le-ați primit deja.
adăugat autor Hans Passant, sursa
arunca o excepție? "a ajuns" la sfârșitul fișierului dvs.Func pare mai bine decât uciderea brutală a firului.
adăugat autor Bond, sursa

2 răspunsuri

Anularea unui fir, atunci când acesta este într-o stare necunoscută, nu este recomandabil. Spuneți, firul execută în prezent un constructor static. Ctorul static va fi anulat și niciodată nu va mai fi rulat (deoarece defecțiunea CTC statică nu se mai execută niciodată). Ați distrus efectiv situația globală în AppDomain fără să vă recuperați vreodată.

Există o mulțime de alte pericole, de asemenea. Asta nu zboara.

Există două opțiuni de producție care anulează firele:

  1. Cooperativ (setați un eveniment sau un flag boolean în combinație cu Thread.MemoryBarrier)
  2. Nu abandonați firul, ci întregul AppDomain sau proces. Nivelul granularității nivelului de fir este prea mic. Trebuie să ștergeți toate stările legate de acel fir, doo.

I want to stress that you cannot make this work any other way. You will have the strangest faults in production if you insist on aborting threads non-cooperatively.

3
adăugat
Ok, dacă știți codul care rulează, puteți să-l omorâți în siguranță, deoarece este cooperativ în acest fel. Utilizați întreruperea pentru a întrerupe sincronizările în așteptare și Despre pentru orice altceva. Poate ar putea posta codul care este agățat?
adăugat autor usr, sursa
De obicei aș fi de acord, dar acesta este un serviciu care trebuie să ruleze fire paralele masiv. Acest lucru funcționează foarte bine, dar din când în când un fir doar atârnă o dată într-o lună. Am prins toate excepțiile și chiar știm în ce direcție se întâmplă, dar nu poate evita acest comportament. Știu că căut o soluție murdară, dar nu am de ales. De asemenea, granularitatea Thread este ok în cazul nostru, deoarece Threads-ul este inițiat dinamic de Database-Entries creând obiecte prin reflecție. Deci aceste Subiecte sunt complet separate.
adăugat autor Ole Albers, sursa
@OleAlbers - Se pare că încercați să rezolvați problema greșită. În loc să rezolvați motivul pentru care firul dvs. se blochează încercând să rezolvați problema "Cum să omorâți firul spânzurat".
adăugat autor Security Hound, sursa

Thread.Abort attempts to terminate the target thread by injecting an out-of-band (asynchronous) exception. It is unsafe because the exception gets injected at unpredictable points in the execution sequence. This can (and often does) lead to some type of corruption in the application domain because of interrupted writes to data structures.

Thread.Interrupt causes most blocking calls in the BCL (like Thread.Sleep, WaitHandle.WaitOne, etc.) to bailout immediately. Unlike aborting a thread, interrupting a thread can be made completely safe because the exception is injected at predictable points in the execution sequence. A crafty programmer can make sure these points are considered "safe points".

Deci, dacă "o mulțime de cod aici" va răspunde la Thread.Interrupt , atunci ar putea fi o abordare acceptabilă de utilizat. Dar, aș dori să vă conduc mai mult spre modelul de anulare a cooperării. Practic, acest lucru înseamnă că codul dvs. trebuie să efectueze un sondaj periodic pentru o cerere de anulare. TPL are deja un cadru pentru a face acest lucru prin CancellationToken . Dar, ați putea realiza cu ușurință același lucru cu un ManualResetEvent sau cu o variabilă volatilă simplă.

Acum, dacă "o mulțime de cod aici" nu este sub controlul dvs. sau dacă modelul de anulare a cooperării nu va funcționa (probabil pentru că utilizați o bibliotecă defectă a terțe părți), atunci nu aveți deloc altă alegere decât să rotiți un complet separat proces pentru a rula codul riscant. Utilizați WCF pentru a comunica cu procesul și dacă acesta nu răspunde atunci îl puteți omorî fără a distruge procesul principal. Este o mulțime de muncă, dar poate fi singura dvs. opțiune.

3
adăugat