Cri*_*scu 1 c# task-parallel-library async-await asp.net-identity
我试图做一个非常简单的实现,IUserStore基本上:
'|'如果有多个项目,则为pipe()).当我运行以下方法时:
[Fact]
public void Create_A_User()
{
// _session is a valid NHibernate ISession object
using (var userStore = new SimpleUserStore<SimpleIdentityUser>(_session))
using (var userManager = new UserManager<SimpleIdentityUser>(userStore))
{
var user = new SimpleIdentityUser
{
UserName = "kenny_mccormick",
RolesStr = "admin",
};
var createTask = userManager.CreateAsync(user, "the_password");
var result = createTask.Result; // this never finishes...
}
}
Run Code Online (Sandbox Code Playgroud)
最后一行永远不会完成执行.
奇怪的是,UserManager永远不会调用我的任何功能SimpleUserStore; 它在那之前就被卡住了.
以下是我定义的组件:
public class SimpleIdentityUser : IUser
{
public virtual Guid UserId { get; set; }
public virtual string PasswordHash { get; set; }
public virtual string SecurityStamp { get; set; }
public virtual string RolesStr { get; set; }
public virtual string UserName { get; set; }
public virtual string Id
{
get { return UserId.ToString(); }
}
}
Run Code Online (Sandbox Code Playgroud)
public class SimpleUserStore<TUser> :
IUserPasswordStore<TUser>,
IUserRoleStore<TUser>,
IUserSecurityStampStore<TUser>
where TUser : SimpleIdentityUser
{
// ReSharper disable once StaticFieldInGenericType
private static readonly Task EmptyTask = new Task(() => { });
private readonly ISession _session;
public SimpleUserStore(ISession session)
{
_session = session;
}
public Task<TUser> FindAsync(UserLoginInfo login)
{
return Task.FromResult((TUser) null);
}
public Task CreateAsync(TUser user)
{
_session.Save(user);
return EmptyTask;
}
public Task UpdateAsync(TUser user)
{
// updates will (hopefully) be saved automatically when the current session is committed
return EmptyTask;
}
public Task DeleteAsync(TUser user)
{
_session.Delete(user);
return EmptyTask;
}
public Task<TUser> FindByIdAsync(string userId)
{
TUser user = null;
Guid guidId;
if (Guid.TryParse(userId, out guidId))
user = _session.Get<TUser>(guidId);
return Task.FromResult(user);
}
public Task<TUser> FindByNameAsync(string userName)
{
TUser user = _session.Query<TUser>().SingleOrDefault(u => u.UserName == userName);
return Task.FromResult(user);
}
public Task SetPasswordHashAsync(TUser user, string passwordHash)
{
user.PasswordHash = passwordHash;
return EmptyTask;
}
public Task<string> GetPasswordHashAsync(TUser user)
{
return Task.FromResult(user.PasswordHash);
}
public Task<bool> HasPasswordAsync(TUser user)
{
return Task.FromResult(user.PasswordHash != null);
}
public void Dispose()
{
}
public Task AddToRoleAsync(TUser user, string role)
{
new SimpleRoleManager<TUser>(user).AddRole(role);
return EmptyTask;
}
public Task RemoveFromRoleAsync(TUser user, string role)
{
new SimpleRoleManager<TUser>(user).DeleteRole(role);
return EmptyTask;
}
public Task<IList<string>> GetRolesAsync(TUser user)
{
List<string> roles = new SimpleRoleManager<TUser>(user).GetRoles().ToList();
return Task.FromResult((IList<string>) roles);
}
public Task<bool> IsInRoleAsync(TUser user, string role)
{
return Task.FromResult(new SimpleRoleManager<TUser>(user).IsInRole(role));
}
public Task SetSecurityStampAsync(TUser user, string stamp)
{
user.SecurityStamp = stamp;
return EmptyTask;
}
public Task<string> GetSecurityStampAsync(TUser user)
{
return Task.FromResult(user.SecurityStamp);
}
}
Run Code Online (Sandbox Code Playgroud)
可能不那么重要,但无论如何它在这里:
public class SimpleRoleManager<TUser> where TUser : SimpleIdentityUser
{
private const string Separator = "|";
private readonly TUser _user;
public SimpleRoleManager(TUser user)
{
_user = user;
}
public string[] GetRoles()
{
return (_user.RolesStr ?? String.Empty)
.Split(Separator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
}
public bool IsInRole(string roleName)
{
return GetRoles().Contains(roleName);
}
public bool AddRole(string roleName)
{
var roles = GetRoles().ToList();
if (roles.Contains(roleName))
return false;
roles.Add(roleName);
SetRoles(roles);
return true;
}
public bool DeleteRole(string roleName)
{
List<string> roles = GetRoles().ToList();
if (!roles.Contains(roleName))
return false;
roles.Remove(roleName);
SetRoles(roles);
return true;
}
private void SetRoles(IEnumerable<string> roles)
{
_user.RolesStr = String.Join(Separator, roles);
}
}
Run Code Online (Sandbox Code Playgroud)
我一直在UserManager<TUser>用DotPeek 检查课程,但没有发现这种奇怪行为的明显原因.
可能是什么导致了这个?
你的异步方法从根本上打破了,因为你正在为所有操作返回相同的任务......而且从不启动它.我在这里看不到任何"无限循环" - 我只是看到你阻止了一项永远无法完成的任务.
目前还不清楚你希望用你的EmptyTask任务完成什么,但目前它肯定无法帮助你.
此外,不清楚你的代码在任何方面_session.Save都是异步的,除非(etc)真的是异步的.
你可以改善的事情有些通过只是运行额外的任务,例如,
public Task CreateAsync(TUser user)
{
Action action = () => _session.Save(user);
return Task.Run(action);
}
Run Code Online (Sandbox Code Playgroud)
...虽然事实上你立即阻止调用代码中的任务使得它也毫无意义.(目前还不清楚这是如何编译的,因为Task没有Result属性......只是Task<T>.)
正如评论中所指出的,这将创建一个新任务,它将在新线程中有效地同步运行 - 使用比您需要更多的线程,并获得并行性的潜在好处.它没有实现与正确异步数据库调用相同的目标(其中没有任何线程与保存调用相关联 - 只是在返回相关网络响应时完成的任务).
如果你真的不关心它是异步的,你可以使用:
public Task CreateAsync(TUser user)
{
_session.Save(user);
return Task.FromResult<object>(null);
}
Run Code Online (Sandbox Code Playgroud)
这将同步保存(就像您当前的代码一样),但随后返回一个已完成的任务(而不是根据您当前的代码永远不会完成的任务).
| 归档时间: |
|
| 查看次数: |
10202 次 |
| 最近记录: |