c# - UserManager.CreateAsync(user, password) stuck in infinite loop -
i'm trying make simple implementation of iuserstore
essentially:
- use nhibernate
- save users in single table (no claims/logins)
- store role names in same table, in nvarchar column (pipe (
'|'
) separated if multiple items).
when run following method:
[fact] public void create_a_user() { // _session 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; // never finishes... } }
the last line never finish executing.
the weird thing usermanager
never calls of functions in simpleuserstore
; gets stuck before that.
here components defined:
the user class:
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 { { return userid.tostring(); } } }
the user store:
public class simpleuserstore<tuser> : iuserpasswordstore<tuser>, iuserrolestore<tuser>, iusersecuritystampstore<tuser> 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 (hopefully) saved automatically when current session 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); } }
how manage roles
probably not important, here anyway:
public class simplerolemanager<tuser> 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); } }
i have been inspecting usermanager<tuser>
class dotpeek, found no obvious causes weird behavior.
what causing this?
your approach async fundamentally broken @ moment, because you're returning same task all operations... , never starting it. don't see "infinite loop" here - see blocking on task can never complete.
it's not clear hope accomplish emptytask
task, it's not helping @ moment.
furthermore, it's not clear code asynchronous in aspect, unless _session.save
(etc) asynchronous.
you improve things somewhat running tasks, e.g.
public task createasync(tuser user) { action action = () => _session.save(user); return task.run(action); }
... although fact you're blocking on task in calling code makes pointless, too. (it's not clear how compiles @ moment, task
doesn't have result
property... task<t>
does.)
as noted in comments, create new task run synchronously in new thread - using more threads you'd otherwise need, potential benefit of parallelism. doesn't achieve same goals asynchronous database call (where there wouldn't any threads tied save call - task complete when relevant network response returned).
if don't care being asynchronous, can use:
public task createasync(tuser user) { _session.save(user); return task.fromresult<object>(null); }
this synchronously save (just current code does) return completed task (rather task never complete, per current code).
Comments
Post a Comment