Domanda

modifica: questo sembra essere un punto critico, quindi mi limiterò a farlo fuori del modo:

Non sto usando questo per la sincronizzazione. Semplicemente per uccidere compiti a lungo in esecuzione quando non sono più diventano necessari / desiderabile.
Ipoteticamente : assumono questi fili semplicemente scrivere alla console (ad esempio: "filo 1"), un sonno a correre, e quindi uscire. Se sono abortiti, voglio loro di informare me con un'altra scrittura console (dicono: "filo 1 interrotta"). E io voglio essere in grado di saltare dritto per il codice di interruzione se provo ad abortire prima che venga eseguito, senza alcuna possibilità di esso svolgere le sue normali funzioni. Se è interrotto durante il normale funzionamento, sarà naturalmente stampare sia.


Ho un pezzo di discussioni vorrei correre in ordine, su un sito di ASP in esecuzione .NET 2.0 con Visual Studio 2008 (idea di quanto tutto ciò che conta, ma è così), e possono avere abortito da pulire codice up che dovrebbe essere eseguito indipendentemente da quanto lontano attraverso il loro compito sono. Quindi faccio un filo in questo modo:

Thread t = new Thread(delegate() {
   try { 
      /* do things */ 
      System.Diagnostics.Debug.WriteLine("try");
   }
   catch (ThreadAbortException) {
      /* cleanup */ 
      System.Diagnostics.Debug.WriteLine("catch");
   }
});

Ora, se voglio interrompere la serie di discussioni parte fino in fondo, la pulizia può essere ancora più avanti desiderabile in giù la linea. Guardando attraverso MSDN implica puoi .Abort () un filo che non è iniziato, e poi .Start () che, a quel punto verrà inviata l'eccezione ed eseguire normalmente. Oppure si può .join () il filo interrotto per aspettare che finisca abortire. Presumibilmente si possono combinare.

http://msdn.microsoft.com /en-us/library/ty8d3wta(v=VS.80).aspx
Per attendere fino a quando un thread è interrotto, è possibile chiamare il metodo join sul filo dopo la chiamata al metodo Abort, ma non v'è alcuna garanzia l'attesa finirà.
Se Abort è chiamato su un thread che non è stato avviato, il filo si interrompe quando Iniziare viene chiamato. Se interruzione viene chiamato su un filo che viene bloccato o sta dormendo, il filo viene interrotta e quindi interrotta.

Ora, quando il debug e passo attraverso questo codice:

t.Abort(); // ThreadState == Unstarted | AbortRequested
t.Start(); // throws ThreadStartException: "Thread failed to start."
// so I comment it out, and
t.Join(); // throws ThreadStateException: "Thread has not been started."

In nessun punto vedo una qualsiasi uscita, né eventuali punti di interruzione sia sul blocco try o cattura ottenere raggiunto.
Stranamente, ThreadStartException non è elencato come un possibile lancio di .Start (), da qui: http://msdn.microsoft.com/en-us/library/a9fyxz7d (v = VS.80) aspx (o qualsiasi altra versione)

ho capito questo potrebbe essere evitato con un parametro di avvio, in cui si afferma se il thread dovrebbe passare al codice di pulizia, e rinunciando alla chiamata Abort (che è probabilmente quello che farò). E I potrebbe .Start () il filo, e quindi .Abort () esso. Ma come una quantità di tempo indeterminato può passare tra .Start e .Abort, sto considerando è inaffidabile, e la documentazione sembra dire il mio metodo originale dovrebbe funzionare.

mi sto perdendo qualcosa? È il male documentazione?

modifica: OW. E non si può chiamare .Start (param) su un thread non parametrizzato (Start). C'è un modo per scoprire se un thread è parametrizzata o no, a parte tentativi ed errori? Vedo un m_Delegate privato, ma niente pubblico ...

È stato utile?

Soluzione

Quando si utilizza ...

t.Abort();
t.Start();

... l'innerException del ThreadStartExcpetion conterrà il ThreadAbortExeption altrettanto stati MSDN: ( se Abort viene chiamato su un thread che non è stato avviato, il filo si interrompe quando Iniziare si chiama )

Se si esegue ...

t.Start();
t.Abort();

... il ThreadAbortException non può mai occure perché il thread non ha avuto il tempo di iniziare prima che fosse interrotta.

Se si prova qualcosa di simile ...

t.Start();
Thread.Sleep(100);
t.Abort();

... deve essere sempre eseguito il codice "pulizia".

Se è necessario eseguire la pulizia del codice, anche se il filo non si è iniziato a fare qualsiasi cosa una possibile soluzione sarebbe di avviare un metodo di pulizia insieme con la chiamata Abort.

Inoltre si dovrebbe cercare di evitare di interrompere le discussioni e utilizzare tecniche diverse (http://msdn.microsoft.com/en-us/library/ms228964.aspx)

Altri suggerimenti

mi rendo conto di ciò che implicava la documentazione a voi, ma questo non è ciò che accade. Se si interrompe un filo e poi avvia, non sarà mai eseguito in alcun modo. Il CLR è abbastanza intelligente per sapere quel filo-Aborts sono un business precario, e la possibilità di saltare l'esecuzione del thread del tutto è quindi da non perdere.

Forse rendere il codice di pulitura in una subroutine. Se i Interrompe filo genitore o sa di l'interruzione, chiama il codice di pulitura in modo esplicito.

Tenete a mente che di .net nozione di "ripulire" dopo l'interruzione di un filo, è quello di scaricare il dominio applicazione delle assemblee che sono state eseguendo il filo interrotto. E 'un altro modo per dire "non aspettatevi questo per ripulire bene." Si dovrebbe prima cercare sempre un design che non richiede discussioni abortire.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top