c# - Syncronization of async EF Tasks -
i working on application processes company resources. have ms sql database , working entityframework 6.1.3 , .net4.5. dbcontext has async methods example
protected task<int> savechangesasync();
i know dbcontext not thread safe , dont want call async operations intend executed parallel. need free gui thread while polling database.
normally go , programm await keywords , "just carefull" not call 2 async operations @ same time application supposed up-to-date. therefor have server connection. everytime other user updates database polling command sent applications working on database. polling command anytime , therefor racecondition user initiated async polling of database.
what want queue each task after previous one. dont know how or if idea. far tried working task.continuewith() noticed tasks never starting , therefor wait forever.
here code far
(_lastrunningtask declared in dbcontext inhereting class , initialized in constructor :
_lastrunningtask = task.run(() => { thread.sleep(1); });
)
private task _lastrunningtask; private task<int> savechangesasyncimpl(cancellationtoken cancellationtoken) { return validateentitiesasyncimpl().continuewith(p => savechangesasync(cancellationtoken)).unwrap(); } public override int savechanges() { task<int> t = _lastrunningtask.continuewith(p => savechangesasyncimpl(cancellationtoken.none)).unwrap(); _lastrunningtask = t; return t.result; } public override task<int> savechangesasync() { return savechangesasync(cancellationtoken.none); } public override task<int> savechangesasync(cancellationtoken cancellationtoken) { task<int> t = _lastrunningtask.continuewith(p => savechangesasyncimpl(cancellationtoken)).unwrap(); _lastrunningtask = t; return t; } public task validateentitiesasync() { return _lastrunningtask = _lastrunningtask.continuewith(p => validateentitiesasyncimpl()).unwrap(); } private task validateentitiesasyncimpl() { return task.run(() => { changetracker.detectchanges(); list<dbentityentry> allentites = new list<dbentityentry>(changetracker.entries()); try { foreach (dbentityentry entity in allentites) { if (entity.state == entitystate.deleted) ((entitybase)entity.entity).readytodelete(); } } catch (errorexception e) { fireerror(e); throw e; } catch (exception e) { return; } return; }); } public task revertchangesasync<tentity>(cancellationtoken token) tentity : entitybase { return _lastrunningtask = _lastrunningtask.continuewith(p => revertchangesasync<tentity>(token)).unwrap(); } private task revertchangesasyncimpl<tentity>(cancellationtoken token) tentity : entitybase { return task.run(() => revertdummy<tentity>(token)); } private async void revertdummy<tentity>(cancellationtoken token) tentity : entitybase { changetracker.detectchanges(); list<dbentityentry<tentity>> revertentries = new list<dbentityentry<tentity>>(changetracker.entries<tentity>()); foreach (dbentityentry entity in revertentries) { await entity.reloadasync(token); } }
i know dbcontext not thread safe , dont want call async operations intend executed parallel.
dbcontext
indeed not thread-safe. but, doesn't mean query concurrently. async
, there no thread. don't need use task.run
of work want do. take advantage naturally async api's offered entity framework.
as long start new instance of dbcontext
each query, fine.
for example:
private async task revertdummyasync<tentity>( entity entity, cancellationtoken token) tentity : entitybase { using (var context = new somedbcontext()) { changetracker.detectchanges(); list<dbentityentry<tentity>> revertentries = new list<dbentityentry<tentity>>(changetracker.entries<tentity>()); foreach (dbentityentry entity in revertentries) { await entity.reloadasync(token); } } }
and can call on collection of entities:
var collections = new list<entity>(); var tasks = collections.select(x => revertdummyasync<entity>(x)); await task.whenall(tasks);
Comments
Post a Comment