❔ Cancel task on nested exception

I have a series of nested async methods, when a exception is thrown I want to cancel the task. The main issue is that I need to do a try cache in a for loop in a nested method, so that we can get more detailed telemetry about it. That means that the methods just keep going. I could pass the CTS to the tasks instead, or access it through other means, but that also feels a little messy. Hope this makes sense.
private CancellationTokenSource _tokenSource;
public async Task RunBigTask()
{
_tokenSource = new CancellationTokenSource();
// Some logic here...
await OtherClass.RunSmallerTasks(_tokenSource.Token);
// Some other logic here...
}

// In another class...
public async Task RunSmallerTasks(CancellationToken ct)
{
for(int i = 0; i < k; i++)
{
ct.ThrowIfCancellationRequested();
try
{
await RunSmallTask();
}
catch(Exception e)
{
// Sending telemetry here about the exception.
}
}
}
private CancellationTokenSource _tokenSource;
public async Task RunBigTask()
{
_tokenSource = new CancellationTokenSource();
// Some logic here...
await OtherClass.RunSmallerTasks(_tokenSource.Token);
// Some other logic here...
}

// In another class...
public async Task RunSmallerTasks(CancellationToken ct)
{
for(int i = 0; i < k; i++)
{
ct.ThrowIfCancellationRequested();
try
{
await RunSmallTask();
}
catch(Exception e)
{
// Sending telemetry here about the exception.
}
}
}
2 Replies
Erroneous Fatality
A cancellationToken can only be cancelled through its source, so you're right, you'd have to pass it down, and that would be messy. I always viewed cancellationToken's as inverse exceptions. Exceptions break the execution from the bottom to the top, and cancellation tokens break execution from the top to the bottom. If I've understood you correctly, you want to stop the execution of RunSmallerTasks and RunBigTask when any of the RunSmallTask breaks? In that case all you need to do is rethrow the exception from the RunSmallTask after you've logged it in telemetry. It will bubble up until the next try catch block or until it stops the whole program.
public async Task RunSmallerTasksAsync(CancellationToken cancellationToken = default)
{
for(int i = 0; i < k; i++)
try
{
await RunSmallTaskAsync(cancellationToken); // Use the cancellationToken inside your small task, no need to check it here.
}
catch(Exception exception)
{
// Sending telemetry here about the exception.
throw exception;
}
}
public async Task RunSmallerTasksAsync(CancellationToken cancellationToken = default)
{
for(int i = 0; i < k; i++)
try
{
await RunSmallTaskAsync(cancellationToken); // Use the cancellationToken inside your small task, no need to check it here.
}
catch(Exception exception)
{
// Sending telemetry here about the exception.
throw exception;
}
}
Accord
Accord8mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.