Cancelling one of the concurrently executed methods

79 views Asked by At

I am using Task.WaitAny to call 3 different methods (TrySolution1, TrySolution2 and TrySolution3) concurrently. My requirement is to find which method gets executed first and abort/cancel the other methods execution, If the first method returns result.

Tried using CancellationTokenSource to perform cancellation of the other tasks once the first method executes, but could see that the other methods still executes.

My code snippet:

Task<Boolean>[] tasks = new Task<Boolean>[3];

CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;

tasks[0] = Task<Boolean>.Factory.StartNew(() => TrySolution1());
tasks[1] = Task<Boolean>.Factory.StartNew(() => TrySolution2());
tasks[2] = Task<Boolean>.Factory.StartNew(() => TrySolution3());

Task.WaitAny(tasks, ct);
cts.Cancel();
2

There are 2 answers

0
Harrison On

You need to set the cancellation token to cancelled at the end of each attempt and then check for it in each method to see if it was cancelled at some point. Something like this...check out Task Cancellation

Be careful though. This will set the cancellation task, so although one task will complete the token will still be set.

    var tokenSource = new CancellationTokenSource();
    CancellationToken ct = tokenSource.Token;

    var task[0] = Task.Factory.StartNew(() =>
    {

        // Were we already canceled?
        ct.ThrowIfCancellationRequested();

        bool moreToDo = true;
        while (moreToDo)
        {
            // Poll on this property if you have to do 
            // other cleanup before throwing. 
            if (ct.IsCancellationRequested)
            {
                // Clean up here, then...
                ct.ThrowIfCancellationRequested();
            }

        }

        tokenSource.Cancel();
    }, tokenSource.Token); // Pass same token to StartNew.
0
svick On

There is no forced aborting of code that's already executing in the TPL. What you need to do is to pass the CancellationToken into all of your TrySolutionN methods and then check it at appropriate points when executing them or pass it to methods you're calling from them.

To check whether the passed-in token is canceled in TrySolutionN, use ThrowIfCancellationRequested() or IsCancellationRequested.