views:

156

answers:

1

Hi,

I'm trying to implement a cancellable worker thread using the new threading constructs in System.Threading.Tasks namespace. So far I have have come up with this implementation:

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.
        }
    }
}

When Stop() returns I expect Worker.Status to be TaskStatus.Canceled.
My unit tests have shown that under certain conditions Worker.Status remains set to TaskStatus.Running.

Is this a correct way to implement a cancellable worker thread?

+3  A: 

I believe that the problem is in your call to

Worker.Wait(_cancellationTokenSource.Token);

That's waiting for the token to be signalled - which it already is, because you've just called Cancel(). If you change that to just

Worker.Wait();

then I believe you'll see a state of RanToCompletion. You won't see Canceled, because your task isn't throwing OperationCanceledException. If you change your RunTasks method to call

cancellationToken.ThrowIfCancellationRequested()

at the end, then you'll need to catch an AggregateException in Stop - but then you'll see a state of Canceled at the end.

At least, that's what my experimentation shows :)

Jon Skeet
Yes, that fixed the issue. Thanks.
Arnold Zokas