When canceling a task that has a timeout (before the timeout has ended) using a cancel token an exception is thrown. Example:
mytask.start();
bool didTaskRunInTime = mytask.wait(5 mins, _cancelToken);
Which means I cannot go on like below.
//was the task cancelled
if (_cancelToken.IsCancelRequested)
{
// log cancel from user to file etc
}
if (didTaskRunInTime )
{
int taskResult = myTask.Result;
// log result to file
}
else if (!_cancelToken.IsCancelRequested)
{
// Tell user task timed out , log a message etc
}
I will have to do all this in my catch block and my code is looking messy. What is the correct way to do this?
You could call Task.WaitAny
with an array of just that task. Then you can act on the status of the task, however the method returns. Sample code:
using System;
using System.Threading;
using System.Threading.Tasks;
class Test
{
static void Main()
{
Task sleeper = Task.Factory.StartNew(() => Thread.Sleep(100000));
int index = Task.WaitAny(new[] { sleeper },
TimeSpan.FromSeconds(0.5));
Console.WriteLine(index); // Prints -1, timeout
var cts = new CancellationTokenSource();
// Just a simple wait of getting a cancellable task
Task cancellable = sleeper.ContinueWith(ignored => {}, cts.Token);
// It doesn't matter that we cancel before the wait
cts.Cancel();
index = Task.WaitAny(new[] { cancellable },
TimeSpan.FromSeconds(0.5));
Console.WriteLine(index); // 0 - task 0 has completed (ish :)
Console.WriteLine(cancellable.Status); // Cancelled
}
}
Note that if the task is faulted, you should "observe" the exception in order to avoid it going bang when it's finalized :)