我已根据此Microsoft example实现了AuthenticateAsync。
根据示例,AuthenticateAsync()包含
IPrincipal principal = await AuthenticateAsync(userName, password, cancellationToken);
我已实现通过System.Data.SqlClient.SqlConnection(在I / O上阻塞)调用SQL Server数据库 - 这会导致警告
这种异步方法缺少'await'运算符,并且会同步运行。
docs表示AuthenticateAsync必须返回
将执行身份验证的任务。
我考虑过
应该我在做什么?
可以在AuthenticateAsync中阻止吗?
答案 0 :(得分:2)
SqlConnection
和相关类型支持异步操作,因此您应该使用它们。这样,您就不需要任何变通办法,也不会因阻塞而浪费线程。
如果由于某种原因,你真的不能
忽略警告
更好的选择是让方法非async
并使用Task.FromResult()
来创建您需要返回的Task
。这摆脱了警告,也略微提高了效率。
在Task.Run()
中换行阻止调用这会使IIS使用的昂贵线程数增加一倍吗?
它不会使线程数加倍,await
不会阻塞线程,只有你的同步IO会。但它确实会因调度,同步和上下文切换而导致一些开销,因此它并不理想。 Task.FromResult()
将是更好的选择。
答案 1 :(得分:1)
我想说有两种方法可以解决这个问题。
第一种是忽略警告,如你自己所暗示的那样。这样做的唯一方法是使方法同步。这将导致IIS保持昂贵的I / O线程比它更长,但不会有其他不良影响。
第二种方法是使对数据库的调用异步并等待其结果。你没有提到你要连接的数据库,所以很难判断这是否容易。
如果可能,我会建议第二次实施。
答案 2 :(得分:1)
我已经实现了对数据库的调用(阻塞 I / O) - 导致警告
这种异步方法缺乏等待'运营商并将同步运行。
归结为AuthenticateAsync
的实施。如果您在这里进行数据库调用,应该可以在您的实现中使用await
运算符,假设您的Db提供程序支持它(许多包括Ado.NET for SqlClient,Entity Framework等)。在这种情况下,正确的实现就是这样做。这是解决方案,因为async / await框架可以将线程返回到线程池,直到数据库工作完成,此时代码恢复执行。这是在Web框架中运行的I / O调用的首选实现,因为线程随后被释放以提供其他传入请求,而不是被迫等待I / O完成并基本上阻塞。
编辑 根据您的上一次修改
因为您使用的是SqlClient
,所以您可以在此处使用异步调用并等待它们。因此,正确的解决方案是更改AuthenticateAsync
的实现,将async
关键字保留在方法实现签名中,并将await
数据库调用代码生成。