In a driver, I have a button to force a refresh.
This refresh run a comparison between the actual elements provisioned in the DMS and the elements expected to be provisioned in a database.
The processing can take a long time (several hours) and I would like to add the possibility to cancel the task. For the moment only a restart of the element allows to do this.
How can I catch this cancel and stop the processing?
Hi Yvan,
I don't know if there is any out-of-the-box way of doing what you are trying to achieve, however, it should be possible to apply similar concepts to what is used in multithreaded scenarios.
One approach you could do is to use the queued option in the QAction definition (Docs Ref), which is actually also useful so you do not have an RTE from a QAction running for too long (the several hours you mention).
With the queued option the QAction will run in the background allowing you to continue executing other operations and you can take advantage of this fact to trigger it to start an operation and also to stop the operation even before the first execution has finished.
Since each time you trigger the QAction it will run in a separate thread, you will have to be careful to implement the proper locking to ensure data correctness and also make sure you take the necessary precautions to not keep the thread running even after the element has been stopped or even deleted.
But with these safeties in place, you can add a global variable within the scope of the QAction class (do not forget to remove the static option from the Run method) which would then implement a mechanism similar to a CancellationToken from C#.
When clicking the button to Run, you would set the variable to "Run" and check every so often if it is still with the same value and proceed with another chuck of work.
When clicking the button to Cancel, you would set the variable to "Cancel" and exit.
In addition to what Joao indicated I like to mention that it is best practice to keep the execution time of a qaction-run as small as possible.
In your use-case, you know the action (the end goal) you want to perform will take a lot of time. In those scenario's I advise to chunk the action into smaller pieces and run the execution loop of those smaller pieces via groups. This will allow you to add not only a cancel flow ( = stopping the execution loop), but also any other action increasing the user interaction/satisfaction and keeping the DataMiner Watchdog safety ( not using queued option) to verify if something drastically went wrong.
Also keep in mind that a click on a button that will trigger a QAction will block the SetParameter Thread until that click can be seen as finished = QAction logic has finished. This means that any other sets are impacted (delayed). So it is really better to chunk the actions to perform into smaller bits and execute them via the execution of groups. iso of running everything at once in 1 QAction thread.
Thank you for your advice
Thank you for your answer. We implemented what you proposed