Search code examples
c#cancellationblockingcollection

How to cancel Actions already in a BlockingCollection<Action>


I have a simple class that enqueues actions to execute:

BlockingCollection<Action> blockingCollectionOfEvents = new BlockingCollection<Action>();

System.Threading.Thread workerThread;

public EventQueue()
{
    this.workerThread = new Thread(DequeueEvents);
    this.workerThread.Start();
}

public void EnqueueEvent(Action action)
{
    if (this.blockingCollectionOfEvents.IsAddingCompleted == false)
    {
        this.blockingCollectionOfEvents.Add(action);
    }
}

void DequeueEvents()
{
    foreach (Action action in this.blockingCollectionOfEvents.GetConsumingEnumerable())
    {
        action.Invoke();
    }
}

All is working fine.
Now I need to cancel the tasks already inside the BlockingCollection but as these tasks must release an allocated resource, I can't just empty the BlockingCollection.
I need to signal these tasks to execute an alternate code just to free the resource.
What would be the best solution? Send a reference to a "cancel object" that I send also as a parameter to each task? Or is there a better solution?


Solution

  • I ended up using a static bool and it works, this is the quickest solution so I don't change all my code.

    In my EventQueue object:

    public volatile static bool bCancelAll = false;
    

    And the client object using it also sends the static bool from EventQueue, so inside the CalculateTask function I can use it to make decisions accordingly:

    this.eventQueue.Enqueue(() => CalculateTask(idToProcess, EventQueue.bCancelAll));
    

    To cancel all then I just do:

    EventQueue.bCancelAll = true;