Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task cancellation best practices

Lets say I have a processor who's job is to persist files back to the disk. This is running as a Task while observing a BlockingCollection<T> for files to process.

When the task gets cancelled and there are still files which should be saved to the disk, what would be a good practice for doing so?

It would be convenient to let the task right before exiting quickly write the files remaining back to the disk although I'm not sure if this conflicts with the philosophy of cancelling a task (since cancellation should happen as quick as possible).

Another option is having a second procedure after cancelling the task who's job is to write the remaining files to the disk.

Code example:

class FileProcessor
{
    private readonly BlockingCollection<Stream> input;

    public FileProcessor(BlockingCollection<Stream> input)
    {
        _input = input;
    }

    public Task Run(CancellationToken cancellationToken, 
        BlockingCollection<Stream> input)
    {
        return Task.Factory.StartNew(() => 
        {
            foreach (Stream stream in 
                        input.GetConsumingEnumerable(cancellationToken))
            {
                WriteToDisk(stream);
            }

            // Should I call WriteRemaining here or should I have
                    // a process running after this task exited which 
                    // will call WriteRemaining
            WriteRemaining();
        });
    }

    public void WriteRemaining()
    {
        foreach (Stream stream in input)    
        {
            WriteToDisk(stream);
        }
    }
}

I know this is a bit of an open question, the application/requirements/amount of files to write also play a role but I'm seeking for the general guideline/best practices here.

like image 517
Polity Avatar asked Nov 16 '11 15:11

Polity


1 Answers

Cancellation is a cooperative action when working with the Task Parallel Library, and yes, cancelling is recommended to be a quick operation.

Remember, this is a cancellation, not a cancellation and cleanup. If you have extra operations that you need to perform as the result of a cancellation, then those operations should occur outside of the original task that was cancelled.

Note that this doesn't stop you from calling ContinueWith and performing an operation in a new Task which checks to see if the IsCanceled property returns true and then performs the cleanup based on that.

The key point here is that you don't want to block the original Task that was cancelled, but you are free to start a new Task to perform whatever cleanup you need to do as a result of the cancellation.

like image 124
casperOne Avatar answered Sep 29 '22 02:09

casperOne