2010-05-31 11 views
5

Sto cercando di implementare un thread di lavoro cancellabile utilizzando i nuovi costrutti di threading nello spazio dei nomi System.Threading.Tasks. Finora ho hanno escogitato questa implementazione:Come implementare thread di lavoro cancellabile

public sealed class Scheduler 
{ 
    private CancellationTokenSource _cancellationTokenSource; 
    public System.Threading.Tasks.Task Worker { get; private set; } 

    public void Start() 
    { 
     _cancellationTokenSource = new CancellationTokenSource(); 

     Worker = System.Threading.Tasks.Task.Factory.StartNew(
      () => RunTasks(_cancellationTokenSource.Token), 
      _cancellationTokenSource.Token 
     ); 
    } 

    private static void RunTasks(CancellationToken cancellationToken) 
    { 
     while (!cancellationToken.IsCancellationRequested) 
     { 
      Thread.Sleep(1000); // simulate work 
     } 
    } 

    public void Stop() 
    { 
     try 
     { 
      _cancellationTokenSource.Cancel(); 
      Worker.Wait(_cancellationTokenSource.Token); 
     } 
     catch (OperationCanceledException) 
     { 
      // OperationCanceledException is expected when a Task is cancelled. 
     } 
    } 
} 

Quando Stop() rendimenti mi aspetto di essere Worker.StatusTaskStatus.Canceled.
I miei test di unità hanno dimostrato che in determinate condizioni Worker.Status rimane impostato su TaskStatus.Running.

È un metodo corretto per implementare un thread di lavoro cancellabile?

risposta

5

Credo che il problema è nella chiamata a

Worker.Wait(_cancellationTokenSource.Token); 

che è in attesa del Token essere segnalato - che lo è già, perché hai appena chiamato Cancel(). Se si modifica che a poco

Worker.Wait(); 

allora credo si vedrà uno stato di RanToCompletion. Non vedrai Annullato, perché il tuo compito non è il lancio di OperationCanceledException. Se si cambia il metodo di RunTasks chiamare

cancellationToken.ThrowIfCancellationRequested() 

alla fine, allora avrete bisogno di prendere un AggregateException in Stop - ma poi vedrete uno stato di Canceled alla fine.

Almeno, questo è quello che mostra la mia sperimentazione :)

+0

Sì, questo ha risolto il problema. Grazie. –

Problemi correlati