Cancel a multi-source task

I currently have an application in which I am creating a series of Tasks that are executed one after another, with a cancellation source that can interrupt the execution between Tasks (that is, at safe completion points). Currently, I use this cancellation source only when the control class is Disposed, as a way to quickly and quickly terminate execution.

Now I have a precedent when I would like to create an automatic timeout to cancel the task sequence if the operator does not respond in a timely manner (some of the tasks wait for the operator to interact with the physical mechanism.) At the same time, I still need to support cancellation if the class Disposed Management. I found a CancellationTokenSource.CreateLinkedTokenSource that sounds the way I need it, but I have a few problems:

  • Several series of tasks can be performed in parallel, so I need to create a new CancellationTokenSource to cancel the timeout and associated source for each series of tasks that I start with. CancellationTokenSource implements IDisposable, which means that I need to save both cancellation sources and delete them after the last task is completed or when any of the subtasks is canceled or malfunctioning. This seems rather inconvenient, even with the useful magic of closing an anonymous method (there are still these cancellation sources that are passed.)

  • I also need to protect against the condition where cancel sources are selected before the timer expires (therefore, I will not cancel the selected source). This is a potential race condition, so I need to add an appropriate lock, It also seems inconvenient, adds significant complexity (future maintenance costs) and makes unit testing more difficult (race conditions are difficult to reliably trigger.)

Am I heading the right way here or is there an easier way to do this?

+6
source share
1 answer

The main problem in your question seems to be related to calling Dispose() for Task objects and / or CancellationTokenSource . In this case, I would recommend just not calling Dispose on them, which should greatly simplify your design.

As a rationale, I will give you this topic . In particular, Stephen Tub (the prime minister responsible for the Task) offers you:

dispose of aggressively if it is easy and correct to do based on the structure of your code. If you have to make weird vibrations for Dispose (or in the case of tasks, use additional synchronization to ensure that it is placed securely, since Dispose can only be used after the task is completed), it is best to rely on things to take care of completion.

It sounds like the exact situation that he describes at the end - you are trying to make weird vibrations to call Dispose() on these objects.

+9
source

Source: https://habr.com/ru/post/889975/


All Articles