Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CancellationToken with async Dapper methods?

I'm using Dapper 1.31 from Nuget. I have this very simple code snippet,

string connString = ""; string query = ""; int val = 0; CancellationTokenSource tokenSource = new CancellationTokenSource(); using (IDbConnection conn = new SqlConnection(connString)) {     conn.Open();     val = (await conn.QueryAsync<int>(query, tokenSource.Token)).FirstOrDefault(); } 

When I press F12 on QueryAsync, it points me to

public static Task<IEnumerable<T>> QueryAsync<T>      (         this IDbConnection cnn,          string sql,          dynamic param = null,          IDbTransaction transaction = null,          int? commandTimeout = null,          CommandType? commandType = null      ); 

There is no CancellationToken on its signature.

Questions:

  • Why is the snippet completely buildable assuming that there is no compiler error on the whole solution?
  • Forgive me that I cannot test if calling tokenSource.Cancel() would really cancel the method because I don't know how to generate a long running sql query. Will the .Cancel() really cancel the method and throw OperationCancelledException?

Thank you!

like image 504
Pedigree Avatar asked Aug 28 '14 04:08

Pedigree


People also ask

Can a CancellationToken be reused?

Therefore, cancellation tokens cannot be reused after they have been canceled. If you require an object cancellation mechanism, you can base it on the operation cancellation mechanism by calling the CancellationToken.

What is CancellationToken CancellationToken?

A CancellationToken enables cooperative cancellation between threads, thread pool work items, or Task objects. You create a cancellation token by instantiating a CancellationTokenSource object, which manages cancellation tokens retrieved from its CancellationTokenSource. Token property.

What is CancellationToken in .NET core?

You can use a CancellationToken to stop a long running operation when the user cancels a request in the web browser. In other words, using a CancellationToken can help you stop long running requests from using resources when the user has stopped or refreshed the web page.

What is C# CancellationTokenSource?

A CancellationTokenSource object, which provides a cancellation token through its Token property and sends a cancellation message by calling its Cancel or CancelAfter method. A CancellationToken object, which indicates whether cancellation is requested.


1 Answers

You are passing the cancellation token as the parameter object; that won't work.

The first async methods in dapper did not expose a cancellation token; when I tried to add them as an optional parameter (as a separate overload, to avoid breaking existing assemblies), things got very confused with "ambiguous method" compilation problems. Consequently, I had to expose this via a separate API; enter CommandDefinition:

val = (await conn.QueryAsync<int>(     new CommandDefinition(query, cancellationToken: tokenSource.Token) ).FirstOrDefault(); 

This then passes the cancellation-token down the chain to all the expected places; it is the job of the ADO.NET provider to actually use it, but; it seems to work in most cases. Note that it can result in a SqlException rather than an OperationCancelledException if the operation is in progress; this again is down to the ADO.NET provider, but makes a lot of sense: you could have interrupted something important; it surfaces as a critical connection issue.

As for the questions:

Why is the snippet completely buildable assuming that there is no compiler error on the whole solution?

Because... it is valid C#, even if it doesn't do what you expect.

Forgive me as I cannot test if calling tokenSource.Cancel() would really cancel the method because I don't know how to generate long running sql query. Will the .Cancel() really cancels the method and throws OperationCancelledException?

ADO.NET provider-specific, but yes it usually works. As an example of "how to generate long running sql query"; the waitfor delay command on SQL server is somewhat useful here, and is what I use in the integration tests.

like image 126
Marc Gravell Avatar answered Sep 19 '22 09:09

Marc Gravell