16

I have a cancellation token like so

   static CancellationTokenSource TokenSource= new CancellationTokenSource();

I have a blocking collection like so

BlockingCollection<object> items= new BlockingCollection<object>();

var item = items.Take(TokenSource.Token);

if(TokenSource.CancelPending)
   return;

When I call

TokenSource.Cancel();

The Take does not continue like it should. If I use the TryTake with a poll the Token shows it is being set as Canceled.

i3arnon
  • 113,022
  • 33
  • 324
  • 344
Kenoyer130
  • 6,874
  • 9
  • 51
  • 73

1 Answers1

20

That's working as expected. If the operation is canceled, items.Take will throw OperationCanceledException. This code illustrates it:

static void DoIt()
{
    BlockingCollection<int> items = new BlockingCollection<int>();
    CancellationTokenSource src = new CancellationTokenSource();
    ThreadPool.QueueUserWorkItem((s) =>
        {
            Console.WriteLine("Thread started. Waiting for item or cancel.");
            try
            {
                var x = items.Take(src.Token);
                Console.WriteLine("Take operation successful.");
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("Take operation was canceled. IsCancellationRequested={0}", src.IsCancellationRequested);
            }
        });
    Console.WriteLine("Press ENTER to cancel wait.");
    Console.ReadLine();
    src.Cancel(false);
    Console.WriteLine("Cancel sent. Press Enter when done.");
    Console.ReadLine();
}
Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • 2
    Is it just me, or this concept of "exception driven development" is weird? Nothing against Jim's answer, that's exactly how MS implemented it. But the fact that I want to cancel an operation is not exceptional, is it? I'm missing an overload that would just return false - similar to those timeout overloads. – Elephantik Mar 24 '22 at 09:52