我需要为aspnetidentity实现自定义存储提供程序。 我好好看了一下,发现了不少。但他们似乎对我来说都不对。
我的理解是,如果你的方法以" async"结尾?而不应该是异步的。
参见从某人的代码中获取的示例,这些代码遍布整个地方。
我发现以下内容极具误导性,因为它根本不是我所能看到的异步:
public Task<TUser> FindByIdAsync(int userId)
{
TUser result = userTable.GetUserById(userId) as TUser; //this is not async
if (result != null)
{
return Task.FromResult<TUser>(result);
}
return Task.FromResult<TUser>(null);
}
应该像这样编码吗?:
public async Task<TUser> FindByIdAsync(int userId)
{
TUser result = userTable.GetUserByIdAsync(userId) as TUser;
if (result != null)
{
return await Task.FromResult<TUser>(result);
}
return await Task.FromResult<TUser>(null);
}
Questions?
做&#34; Task.FromResult&#34;是否正确?我的意思是&#34; Task.FromResult实际上变成了同步?应该是什么?
上述代码的正确方法是什么?怎么样configureAwait(false) async be&#34;一直向下包括datalayer以避免死锁&#34;
任何示例代码/代码段都将不胜感激
非常感谢任何反馈
答案 0 :(得分:3)
代码没有误导性。 ASP.NET Identity框架旨在通过返回$(document).ready(function() {
$(".balls").effect('bounce', { times: 3 }, 'slow');
});
来提供异步接口,并通过在方法名称中添加Task
后缀来指示这一点:
Async
但是,底层提供程序可能没有异步方法。在这种情况下,您无法创建异步实现,但仍然必须实现该接口,并且这样做将完全像在您的第一个代码段中那样使用Task<TUser> FindByIdAsync(int userId)
。
使用同步代码实现异步方法
Task.FromResult
如果你的底层提供者支持异步方法,你应该使用async和await。
使用异步代码实现异步方法
public Task<TUser> FindByIdAsync(int userId)
{
TUser result = userTable.GetUserById(userId) as TUser;
return Task.FromResult<TUser>(result);
}
请注意,未使用public async Task<TUser> FindByIdAsync(int userId)
{
TUser result = (await userTable.GetUserByIdAsync(userId)) as TUser;
return result;
}
。仅当您使用同步代码创建Task.FromResult
并且必须将其转换为异步代码所需的Task.FromResult
时,才需要TResult
。
有时您的基础提供商可以返回所需的Task<TResult>
而无需进一步的工作。在这种情况下,您可以删除异步并等待并仍然提供异步实现。这可以使代码更有效:
Task<TUser>
答案 1 :(得分:0)
初始代码绝对不是异步的。它看起来像是采用这种方式来应对API设计。
然而,建议的更改对我来说也不同步。 Task.FromResult
只是创建一个包含结果的已完成任务,不会使任何异步或执行任何类型的等待代码,因此您不应等待它。
在您的情况下,假设GetUserByIdAsync
返回Task<TUser>
,并假设此代码的全部目的(看起来似乎)始终返回已完成的任务(从不出错或取消),这可能被改写为:
public async Task<TUser> FindByIdAsync(int userId)
{
var tResult = userTable.GetUserByIdAsync(userId);
TUser result = null;
try
{
result = await tResult;
}
except
{
// Bad idea, but here goes to your first snippet
}
return Task.FromResult<TUser>(result);
}
注意:这是一个坏主意,因为@PanagiotisKanavos评论说,它隐藏了一个可能出现故障的状态,你不知道你的null
结果是否来了没有找到用户,或者是否有错误情况:我会避免它。
如果故障/取消状态有效,则可能只是:
public Task<TUser> FindByIdAsync(int userId)
{
return userTable.GetUserByIdAsync(userId);
}
答案 2 :(得分:0)
async
方法是编译器构建将返回承诺 future 的内容的一种方式。对于.NET Framework和C#,这是Task
。
await
指令需要等待,而Task
恰好是一个。它不知道或不关心被调用的方法/操作是否真的是异步的。
Task.FromResult<T>
返回一个已完成的任务,如果您在await
方法内的async
指令中使用它,它将被视为已同步完成并继续执行。
因此,使用async
和await
只调用Task.FromResult<T>
最终只会浪费CPU周期和内存,编译器会生成会浪费更多CPU周期和内存的代码在运行时。
由于async
方法始终会返回Task
,因此我们决定将其隐含以提高可读性并为其提供某种同步感觉。编译会将返回值包装在Task
中。这就是为什么您无法直接返回Task.FromResult<TUser>(result)
或Task.FromResult<TUser>(null)
并等待它获取价值的原因。
因此,同步代码的async
等价物将是:
public async Task<TUser> FindByIdAsync(int userId)
{
var result = await userTable.GetUserByIdAsync(userId) as TUser;
if (result != null)
{
return result;
}
return null;
}
或者:
public async Task<TUser> FindByIdAsync(int userId)
{
return await userTable.GetUserByIdAsync(userId) as TUser;
}