dotnet / dotnet/SqlClient

DbCommand.ExecuteReaderAsync throws TaskCanceledException with wrong CancellationToken

Open
#1,250 7 comments 1 reaction 0 assignees View on GitHub
Dominant language
C#
Stars
989
Forks
340
Avg merge
4d 18h
Merged PRs (30d)
69

Description

I am witnessing this behavior in packages\netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll when running from a .Net Core 3.1 application.

When I call DbCommand.ExecuteReaderAsync with a CancellationToken and cancel it before it finishes, an exception is thrown that contains a TaskCanceledException buried down in the InnerExceptions. I expect that behavior, but the issue is that the TaskCanceledException.CancellationToken is not the CancellationToken that I provided to ExecuteReaderAsync. I do not know where this other CancellationToken is coming from, but I thought we were only supposed to suppress TaskCanceledException in our applications if it is for the provided CancellationToken, so I end up with a lot more unhandled exceptions than I want.

Is it safe to suppress any TaskCanceledException, no matter what CancellationToken it contains? Where does this mystery CancellationToken come from, and could ExecuteReaderAsync just return the CancellationToken given to it?

```c#
using (var cts = new CancellationTokenSource())
{
using (var cmd = db.GetSqlStringCommand(queryString))
{
cts.Cancel();
try
{
using (var rdr = cmd.ExecuteReaderAsync(cts.Token).Result)
{
}
}
catch (Exception ex3)
{
// if you inspect ex3, you will find a TaskCanceledException buried in InnerExceptions, but its CancellationToken is not cts.Token
throw;
}
}
}

```

Additional Comments:
I have tested this with "System.Data.SqlClient.SqlCommand" and "Microsoft.Data.SqlClient.SqlCommand". The result is the same in both cases where the TaskCanceledException holds a new CancellationToken and the TaskCanceledException is wrapped in an AggregateException, so I have to dig down in the exception stack to find the TaskCanceledException , which means I cannot just catch TaskCanceledException.

System.AggregateException: One or more errors occurred. (A task was canceled.)
---> System.Threading.Tasks.TaskCanceledException: A task was canceled.
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at System.Threading.Tasks.Task`1.get_Result()

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.