![](/img/trans.png)
[英]List of error cases in use _userManager.CreateAsync(user, password)
[英]UserManager.CreateAsync(user, password) stuck in infinite loop
我正在嘗試對IUserStore
進行非常簡單的實現,該實現基本上是:
'|'
)分開)。 當我運行以下方法時:
[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...
}
}
最后一行永遠不會完成執行。
奇怪的是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(); }
}
}
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);
}
}
可能不是那么重要,但是無論如何這里是:
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);
}
}
我一直在用DotPeek檢查UserManager<TUser>
類,但是沒有發現明顯的原因導致這種奇怪的行為。
是什么原因造成的?
您的異步方法目前已基本中斷,因為您要為所有操作返回相同的任務……而永遠不會啟動它。 我在這里看不到任何“無限循環”-我只是看到您阻塞了一個永遠無法完成的任務。
目前尚不清楚您希望用EmptyTask
任務完成什么,但目前絕對不能幫助您。
此外,除非_session.Save
(等)確實是異步的,否則不清楚您的代碼在任何方面是否都是真正的異步的。
您可以通過運行額外的任務來對事情進行一些改進,例如
public Task CreateAsync(TUser user)
{
Action action = () => _session.Save(user);
return Task.Run(action);
}
...盡管您隨后立即阻止了調用代碼中的任務,這也變得毫無意義。 (目前還不清楚如何編譯,因為Task
沒有Result
屬性,只有Task<T>
有。)
如評論中所述,這將創建一個新任務,該任務將在新線程中有效地同步運行-使用比您原本需要的線程更多的線程,並具有並行性的潛在好處。 它沒有達到與適當的異步數據庫調用相同的目標(在該調用中不會有任何線程被束縛-只有在返回相關的網絡響應時才能完成的任務)。
如果您真的不關心它是異步的,則可以使用:
public Task CreateAsync(TUser user)
{
_session.Save(user);
return Task.FromResult<object>(null);
}
這將同步保存(就像您當前的代碼一樣),但隨后返回已完成的任務(而不是根據您的當前代碼永遠不會完成的任務)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.