ASP.NET 标识用户存储:为什么要返回任务?



我已经想了一段时间了,所有UserStore方法都返回Task或类型化Task<T>,但是为什么呢?为什么不直接返回 T? 我知道它们是 Aync 方法并且是 OWIN 中间件的一部分,这与它有关吗?

我还注意到,一些返回普通旧Task的方法实际上返回了一个空Task。 asp.net 网站的示例返回Task.FromResult<object>(null)http://www.asp.net/identity/overview/extensibility/overview-of-custom-storage-providers-for-aspnet-identity。 我也看过Task.FromResult(0),如果我返回一个带有Action的任务:

return new Task(() =>
{
context.User.Add(new User); context.SaveChanges()
})

然后,不会调用Task内的Action。为什么会这样,返回空Task有什么意义?在我看来,返回Task类似于void方法,对吗?

首先,我真的建议您阅读MSDN/使用异步和Await进行异步编程,这对于了解所有异步/等待的工作原理(幕后)非常有帮助。

实际使用这些技术的原因是UserManager实现通常意味着对数据库工作,这在计算机时间中是"慢的"(Jeff Atwood关于该主题的精彩阅读:http://blog.codinghorror.com/the-infinite-space-between-words/)。

出于这个原因,UserManager方法为您提供了将来为您提供TypeXResultY的承诺,但这需要时间。为了在应用程序等待数据库应答时释放资源(例如),将等待线程置于睡眠状态返回到 ThreadPool,并且释放的容量可用于另一个传入请求(或在此期间可能异步完成的任何任务)。

编辑:谢谢希伯特@Neil

根据 MSDN/异步编程文档:

异步对于可能阻塞的活动至关重要, 例如,当您的应用程序访问 Web 时。访问网络 资源有时会变慢或延迟。如果此类活动被阻止 在同步进程中,整个应用程序必须等待。在一个 异步进程,应用程序可以继续其他工作 这不依赖于 Web 资源,直到潜在的阻塞 任务完成。

数据库调用(特别是在 Microsoft Azure 等云环境中)会阻止 I/O 进程,因此 ASP.NET 标识系统中的大多数 API 都是异步的。

为什么空Task?返回空TaskAsync/Await Programming模型中的最佳实践。异步方法有三种可能的返回类型:TaskTask<T>;和void,但异步方法的自然返回类型只是TaskTask<T>。从同步代码转换为异步代码时,任何返回类型T的方法都将成为返回Task<T>的异步方法,任何返回void的方法都将成为返回Task的异步方法。

  • 异步 void 方法具有不同的错误处理语义。当一个 异常从异步任务或异步任务方法中抛出, 捕获该异常并将其放置在 Task 对象上。使用异步 void 方法,没有 Task 对象,因此抛出任何异常 的异步 void 方法将直接在 同步异步 void 方法时处于活动状态的上下文 开始。
  • 异步 void 方法具有不同的组合语义。异步方法 返回任务或任务可以使用 await 轻松撰写, Task.WhenAny、Task.WhenAll 等。返回 void 的异步方法 不要提供一种简单的方法来通知调用代码他们有 完成。启动几个异步 void 方法很容易,但它是 不容易确定他们什么时候完成。异步无效方法将 在开始和完成时通知他们的同步上下文,但 自定义同步上下文是一个复杂的常规解决方案 应用程序代码。
  • 异步无效方法很难测试。因为差异 在错误处理和撰写中,很难编写单元测试 调用异步 void 方法。MSTest 异步测试支持 仅适用于返回任务或任务的异步方法。有可能 以安装同步上下文,以检测何时所有异步无效 方法已完成并收集任何异常,但很多 更容易让异步 void 方法返回任务。

您应该更喜欢async Task而不是async voidAsync Task方法使错误处理、可组合性和可测试性更加容易。有关更多信息,请阅读本文:异步编程的最佳实践

相关内容

  • 没有找到相关文章

最新更新