1

I've implemented AuthenticateAsync based on this Microsoft example.

As per the example, AuthenticateAsync() contains

IPrincipal principal = await AuthenticateAsync(userName, password, cancellationToken);

which I have implemented to make a call to the SQL Server database via System.Data.SqlClient.SqlConnection (blocking on I/O) - which results in the warning

This async method lacks 'await' operators and will run synchronously.

The docs say AuthenticateAsync must return

A Task that will perform authentication.

I've considered

  • Ignore the warning
    • Not without knowing why Microsoft declared IAuthenticationFilter.AuthenticateAsync async. Perhaps IIS wants to defer execution?
  • Wrap the blocking call in Task.Run()
    • Could this double the number of expensive threads IIS is using?

What should I be doing?

Is it OK to block inside AuthenticateAsync?

Andy Joiner
  • 5,932
  • 3
  • 45
  • 72

3 Answers3

2

SqlConnection and related types support asynchronous operations, so you should use those. That way, you don't need any workarounds and you will not waste threads by blocking.

If, for some reason, you really can't:

Ignore the warning

A better option would be to make the method non-async and use Task.FromResult() to create the Task you need to return. That gets rid of the warning and is also slightly more efficient.

Wrap the blocking call in Task.Run()

Could this double the number of expensive threads IIS is using?

It won't double the number of threads, await does not block a thread, only your synchronous IO will. But it does cause some overhead due to scheduling, synchronization and context switching, so it's not ideal. Task.FromResult() would be a better choice.

Community
  • 1
  • 1
svick
  • 236,525
  • 50
  • 385
  • 514
1

I would say that there are two ways of going about this.

The first is just ignoring the warning as you yourself suggests. The only thing this will do is make the method synchronous. That will cause IIS to hold on to the expensive I/O-thread a little longer than it has to, but will have no other ill effects.

The second way is to make the call to the database asynchronous and await its result. You don't mention what database you are connecting to, so it will be hard to tell if that's easy or not.

If at all possible I would recommend the second implementation.

Falle1234
  • 5,013
  • 1
  • 22
  • 29
1

Which I have implemented to make a call to the database (blocking on I/O) - which results in warning

This async method lacks 'await' operators and will run synchronously.

It comes down to your implementation of AuthenticateAsync. If you are making database calls here it should be possible to use the await operator inside of your implementation assuming that your Db provider supports it (many do including Ado.NET for SqlClient, Entity Framework, etc). In that case the correct implementation is to do that. This is the solution because the async/await framework can then return the thread to the threadpool until the database work is done at which point the code resumes execution. This is the preferred implementation for I/O calls running in a web framework because threads are then freed to serve other incoming requests instead of being forced to wait on I/O to complete and essentially blocking.

EDIT Based on your last edit

Because you are using SqlClient you can use async calls here and await them. So the correct solution is to alter your implementation of AuthenticateAsync, leave the async keyword in the method implementation signature, and await the database calls the code makes.

Igor
  • 60,821
  • 10
  • 100
  • 175