2
\$\begingroup\$

In my assignment I am executing a long running NodeJs script from C# using EdgeJs. Since the script may take a long time to execute, I also want to provide user an option to Cancel the script execution in the middle. The cancellation status is maintained in the database and function IsScripteExecutionCancelled returns true if the user decides to cancel the execution.

To achieve this I am executing script in a background thread using Task.Run(). The main thread contains a while loop that runs until the ScriptExecution is over or is cancelled. I can solve this problem using native System.Threading.Thread, but here I am trying to do it using TPL. Here is the code I have put in place:

bool executionStarted = false;
bool taskCompleted = false;
Result returnValue;

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;

Task executionTask;
while (!(taskCompleted || token.IsCancellationRequested))
{
    if (!executionStarted)
    {
        executionStarted = true;
        executionTask = Task.Run(() =>
        {
            returnValue = ExecuteScript();
            taskCompleted = true;
        }, token);
    }
    bool taskExecutionCancelled = IsScripteExecutionCancelled();
    if (taskExecutionCancelled)
    {
        tokenSource.Cancel();
    }
}

if(token.IsCancellationRequested)
    returnValue= GetDefaultValueForCancellation();

return returnValue;

So, if IsScripteExecutionCancelled returns true the program will come out of the loop and will check if the script was cancelled, in which case I will return a default response. If the ExecuteScript completes my program will return the value returned by function ExecuteScript. I am able to get the desired results using this implementation however I would like to get it validated.

Question: Is it the right way to address this problem?

\$\endgroup\$
  • 1
    \$\begingroup\$ You are going to have to provide more context. It is unclear what this code is suppose to be doing. \$\endgroup\$ – Nkosi Mar 13 '18 at 11:33
  • \$\begingroup\$ This question is incomplete. To help reviewers give you better answers, please add sufficient context to your question. The more you tell us about what your code does and what the purpose of doing that is, the easier it will be for reviewers to help you. Questions should include a description of what the code does \$\endgroup\$ – Dannnno Mar 13 '18 at 13:57
1
\$\begingroup\$

Is there a better way of doing Task cancellation than the one I implemented

There's no task cancellation implemented here. By passing a token to Task.Run you just make the returned task IsCanceled equal to true in case it cancels itself (without, it gets IsFaulted by the OperationCanceledException). But you need (at least) to pass the token to DoSomeWork, because that has to check the token and cancel itself.

Task cancellation works through cooperation of the to-be-canceled task and has nothing to do with Thread.Abort.

\$\endgroup\$
  • \$\begingroup\$ And in addition, neither the token nor its source are passed out to any other code, so there's no way that cancellation could be requested either. \$\endgroup\$ – Peter Taylor Apr 9 '19 at 10:18
0
\$\begingroup\$

you create a variable here and use it only once

bool taskExecutionCancelled = IsScripteExecutionCancelled();
if (taskExecutionCancelled)
{
    tokenSource.Cancel();
}

I would just use the method in the if statement, like

if (IsScripteExecutionCancelled())
{
    tokenSource.Cancel();
}

if you were going to use this value somewhere else and didn't want it evaluated again, then you could assign it to a variable, but then you need to keep in mind that calling the variable will not run the method.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.