'TaskCanceledException: Cancel or timeout?
I only want to use CancellationTokenSource for timeout and cancellation handling.
How to distinguish if a TaskCanceledException occured due to a timeout or due to manual cancellation?
Here is a simplified example. In the real program I neither know if CancellationTokenSource .CancelAfter() was used nor if someone called CancellationTokenSource.Cancel()
static CancellationTokenSource cts = new CancellationTokenSource();
static void Main(string[] args)
{
Task.Run(async () =>
{
try
{
await SomeClass.DoSomething(cts.Token);
}
catch (TaskCanceledException ex)
{
//How to find out if the exception occured due to timeout or a call to cts.Cancel()
}
});
while (true)
{
Thread.Sleep(100);
if (someCondition)
cts.Cancel();
}
}
public class SomeClass
{
public static async Task DoSomething(CancellationToken ct)
{
using (var innerCts = CancellationTokenSource.CreateLinkedTokenSource(ct))
{
innerCts.CancelAfter(1000);
//Simulate some operation
await Task.Delay(10000, innerCts.Token);
}
}
}
thanks
Tom
Solution 1:[1]
AFAIK this is the most commonly used pattern:
Task.Run(async () =>
{
try
{
await SomeClass.DoSomething(cts.Token);
}
catch (OperationCanceledException) when (cts.IsCancellationRequested)
{
// cts cancellation occurred
}
catch (OperationCanceledException)
{
// Timeout occurred
}
});
Another idea is to change the implementation of the SomeClass.DoSomething method, assuming that you are allowed to do it, so that in case of timeout it throws a TimeoutException instead of an OperationCanceledException.
public static async Task DoSomething(CancellationToken cancellationToken)
{
using var innerCts = new CancellationTokenSource(millisecondsDelay: 1000);
using var linkedCts = CancellationTokenSource
.CreateLinkedTokenSource(cancellationToken, innerCts.Token);
try
{
// Simulate some operation
await Task.Delay(10000, linkedCts.Token);
}
catch (OperationCanceledException) when (innerCts.IsCancellationRequested)
{
throw new TimeoutException();
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Theodor Zoulias |
