2015-04-21 7 views
8

Vedo questo codice di fronte a me e io sono sospettoso:Il codice che dispone di CancellationTokenSource mentre le attività vengono annullate correttamente?

CancellationTokenSource _cts; 

public void Dispose(); 
{ 
    _cts.Cancel(); 
    _cts.Dispose(); 
    _task.Wait(); //wait for the task to be canceled!? 
} 

E 'sicuro per chiamare _cts.Dispose() subito dopo annullare? Non eliminerebbe le risorse sottostanti di CancellationTokenSource che sono necessarie per l'attività annullata per attendere Wait on the CancellationToken, se lo desidera?

risposta

7

È sicuro chiamare _cts.Dispose() subito dopo l'annullamento?

Per saperlo, dobbiamo capire cosa succede quando cancelliamo un CancellationTokenSource.

Quando si annulla uno CancellationTokenSource, si attiva per richiamare eventuali richiamate registrate tramite lo CancellationToken, che contiene un riferimento alla propria sorgente padre tramite il metodo CancellationToken.Register().

Ora, quando si smaltisce un CTS, si tenta di annullare la registrazione del richiamo di collegamento registrato dal token. Se è in esecuzione, attenderà il completamento del delegato.

Ciò significa che sebbene sia stato eliminato il CTS, l'oggetto è ancora referenziato dal token. Quindi, non è ancora idoneo per la raccolta.

Ora diamo un'occhiata a CancellationToken.IsCancellationRequested:

public bool IsCancellationRequested 
{ 
    get 
    { 
     return m_source != null && m_source.IsCancellationRequested; 
    } 
} 

Ciò significa che mentre disposto, controllando la disdetta produrrà vero. Ciò significa che è sicuro attendere il completamento delle attività dopo aver chiamato la soluzione.

Come nota a margine, se si tenta (per qualche motivo) di passare un token tramite la sua EliminazioneTokenSource, si otterrà un ObjectDisposedException.

Edit:

Due cose che vorrei aggiungere. Innanzitutto, lasciami dire che non consiglio di utilizzare questo approccio. Dovrebbe funzionare per alcuni percorsi di esecuzione del codice, ma non per tutti. CancellationTokenSource deve essere normalmente eliminato solo se si utilizza la proprietà WaitHandle. Altrimenti, va bene lasciare al GC la pulizia. Ma, dato che è una questione di gusto, puoi scegliere quale ti piace. Sicuramente consiglierei di disporre solo dopo aver accertato che il compito ha rispettato la richiesta di cancellazione.

Come per l'uso di WaitHandle, verrà smaltito e annullato una volta che lo smaltimento, quindi non sarà essere raggiungibile.

+1

Ma IsCancellationRequested non è l'unico scenario di cui preoccuparsi, giusto? Che dire di WaitHandle? –

+0

'WaitHandle' sarà chiuso se dispose corre. Non sono sicuro che l'uso di 'WaitHandle' sia un caso d'uso comune. Lo aggiungerò alla mia risposta. –

+0

@Tim Ho aggiunto una modifica importante alla mia risposta. Anche se quello che stai cercando di fare è * possibile *, non lo consiglierei di certo. –