I have an function that does some work for a few seconds. I'm trying to cancel that task after a certain time period and am unable to do so. My objective is to do the asyncFunction for 5 seconds and then, move onto to a different task. For some reason, I can't seem to await _t1.
private async Task asyncFunction(string line_1, string line_2, string line_3, string line_4, int _time, System.Threading.CancellationTokenSource _cts)
{
_cts.Token.ThrowIfCancellationRequested();
await Task.Run(async () => {
someFunction_01(line_1, line_2, line_3, line_4);
someFunction_01("HELLO WORLD");
await Task.Delay(_time, _cts.Token);
});
}
The way I'm calling my funcion is:
TimeSpan _timeout = TimeSpan.FromSeconds(5);
var timeoutCancellationTokenSource = new System.Threading.CancellationTokenSource(_timeout);
Task _t1 = asyncFunction("LINE 01", " ", " ", " ", 6000, timeoutCancellationTokenSource);
if (await Task.WhenAny(_t1, Task.Delay(_timeout, timeoutCancellationTokenSource.Token)) == _t1)
{
await _t1;
}
else
{
// timeout/cancellation logic
timeoutCancellationTokenSource.Cancel();
}
I can't seem to cancel the Task.Delay inside of the asyncFunction. Any code help is appreciated.
CodePudding user response:
I don't quite understand the purpose of the code. Particulary the if-statement:
if (await Task.WhenAny(_t1, Task.Delay(_timeout, timeoutCancellationTokenSource.Token)) == _t1)
Why pass in a _timeout
to Task.Delay
which is the same timeout as you created the timeoutCancellationTokenSource
with?
If we ignore the first parameter you give Task.Delay
it also means you have two calls to Task.Delay
with the same CancellationToken
and now you have a race-condition where it's impossible to predict which Task.Delay
will be cancelled first.
To show an example of how you can get the cancellation to work, you can do like this:
TimeSpan _timeout = TimeSpan.FromSeconds(1);
var timeoutCancellationTokenSource = new System.Threading.CancellationTokenSource(_timeout);
Task _t1 = asyncFunction("LINE 01", " ", " ", " ", 2000, timeoutCancellationTokenSource);
try
{
await _t1;
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation was cancelled");
}
// Output: Operation was cancelled
If _timeout
is longer than the 2000
milliseconds passed into asyncFunction
the task completes after 2 seconds without being cancelled.
See this fiddle for a test run.