当商店不支持异步方法时,哪个是 ASPNET Identity 的正确实现?

Which is the proper implementation of ASPNET Identity when the store doesn't support async method?

我是 ASP.NET Identity 2.1 和 async/await 编程的新手。

我想将 ASP.NET Identity 与我的用户存储集成,它不支持 'async' 方法,特别是 Telerik 的 OpenAccess。

在 ASP.NET 标识中,所有 IUserStore 接口(和其他 IXXXStores)仅公开 ~Async 方法。似乎强烈鼓励他们实现代码异步运行。不幸的是,Telerik 的 OpenAccess 不支持 ~Async 版本的方法,所以我必须自己实现它。

我搜索了几个例子,我发现很多例子(不支持~Async)是这样的:

public Task<AspNetUser> FindByIdAsync(string userId)
{
    if (string.IsNullOrEmpty(userId)) throw new ArgumentException("userId");

    var user = this.Context.AspNetUsers.Where(o => o.Id == userId).SingleOrDefault();
    return Task.FromResult<AspNetUser>(user);
}

这似乎不是正确的异步代码。当然,按键查找用户可能足够快。不过既然有网络I/O,不应该像follow吗?

public Task<AspNetUser> FindByIdAsync(string userId)
{
    if (string.IsNullOrEmpty(userId)) throw new ArgumentException("userId");

    return Task.Run(() =>
        this.Context.AspNetUsers.Where(o => o.Id == userId).SingleOrDefault()
    ).ConfigureAwait(false);
}

我不确定仅通过 Task.Run 包装同步代码是否使其成为正确的 ~Async 方法。 上面和下面有什么区别:

public async Task<AspNetUser> FindByIdAsync(string userId)
{
    if (string.IsNullOrEmpty(userId)) throw new ArgumentException("userId");

    return await Task.Run(() =>
        this.Context.AspNetUsers.Where(o => o.Id == userId).SingleOrDefault()
    ).ConfigureAwait(false);
}

正确的方法是什么?或者是否有其他方法来实现 ASP.NET 那些商店的身份不支持本机 ~Async 方法?

确实 TaskFactory.FromResult 不是正确的异步代码,特别是因为底层 API 正在执行 I/O-bound 操作(这是异步的完美匹配)。但是,没有 一种方法来强制非异步 API 成为异步 API;你只需要让 Telerik 修复他们的 API.

同时,您提到的任何一种方法都可以,但 TaskFactory.FromResult 方法更优越。作为一般规则,您应该避免在 ASP.NET 上使用 Task.Run,因为它会不必要地干扰线程池。

asynchronous convention 将在任务同步完成时正常工作。当然,该方法是阻塞而不是异步的并不理想,但它会起作用。