Search code examples
c#.nettask-parallel-librarycancellation

Apply CancellationToken in dataflowblock


In my producer-consumer application. I have:

CancellationTokenSource cTokenSource = new CancellationTokenSource();
CancellationToken cToken = new CancellationToken();
cToken = cTokenSource.Token;

Click start button, the application is running.

private async void Start_Click(object sender, RoutedEventArgs e)
{
   var producer = Producer();
   var consumer = Consumer();
   await Task.WhenAll(producer, consumer);
}

In the consumer, I used TPL.

async Task Consumer()
{
    try
    {
        var executionDataflowBlockOptions = new ExecutionDataflowBlockOptions
        {
            MaxDegreeOfParallelism = 50,
            CancellationToken = cToken
        };
        var consumerBlock = new ActionBlock<AppointmentReminder>(
       remainder =>
       {
         // blah blah for long running processes and updating UI
          var result = Run(reminder);
       },
       executionDataflowBlockOptions);

        bufferBlock.LinkTo(
        consumerBlock, new DataflowLinkOptions { PropagateCompletion = true });
        await Task.Delay(500);
    }

Now I have a cancel button, I want to stop the TPL consumer tasks while I click it. How?

private void Cancel_Click(object sender, RoutedEventArgs e)
{

Solution

  • Cancellation in .Net is cooperative. You create a CancellationTokenSource to handle the cancellation and use CancellationToken to be notified of cancellation. To cancel the token simply call CancellationTokenSource.Cancel:

    cTokenSource.Cancel();
    

    BTW, there's no much use in creating a CancellationToken directly as it can never be cancelled. You should get a token from the CancellationTokenSource:

    var cTokenSource = new CancellationTokenSource();
    var cToken = cTokenSource.Token;