c# - Migrating to Async: Repository -


i have large codebase using repositories implement irespository , i'm implementing async versions of methods:

t find(id); task<t> findasync(id); ...etc... 

there several kinds of repository. simplest based on immutable collection universe of entities small enough merit loading them @ once db. load happens first time calls of irepository methods. find(4), example, trigger load if hasn't happened already.

i've implemented lazy < t >. handy , has been working years.

i can't go cold-turkey on async have add async alongside sync versions. problem is, don't know called first - sync or async method on repository.

i don't know how declare lazy - if i've done it,

lazy<mycollection<t>>  

then loading won't async when findasync() called first. on other hand, if go

lazy<task<mycollection<t>>> 

this great findasync() how synchronous method trigger initial load w/o running afoul of mr. cleary's warnings deadlock calling task.result?

thank time!

the problem lazy<t> there's 1 factory method. want synchronous factory method if first call synchronous, , asynchronous factory method if first call asynchronous. lazy<t> won't you, , afaik there's nothing else built-in offers these semantics either.

you can, however, build 1 yourself:

public sealed class syncasynclazy<t> {   private readonly object _mutex = new object();   private readonly func<t> _syncfunc;   private readonly func<task<t>> _asyncfunc;   private task<t> _task;    public syncasynclazy(func<t> syncfunc, func<task<t>> asyncfunc)   {     _syncfunc = syncfunc;     _asyncfunc = asyncfunc;   }    public t get()   {     return getasync(true).getawaiter().getresult();   }    public task<t> getasync()   {     return getasync(false);   }    private task<t> getasync(bool sync)   {     lock (_mutex)     {       if (_task == null)         _task = dogetasync(sync);       return _task;     }   }    private async task<t> dogetasync(bool sync)   {     return sync ? _syncfunc() : await _asyncfunc().configureawait(false);   } } 

or can use pattern without encapsulating it:

private readonly object _mutex = new object(); private task<mycollection<t>> _collectiontask;  private task<mycollection<t>> loadcollectionasync(bool sync) {   lock (_mutex)   {     if (_collectiontask == null)       _collectiontask = doloadcollectionasync(sync);     return _collectiontask;   } }  private async task<mycollection<t>> doloadcollectionasync(bool sync) {   if (sync)     return loadcollectionsynchronously();   else     return await loadcollectionasynchronously(); } 

the "bool sync" pattern 1 stephen toub showed me recently. afaik there's no blogs or yet.


Comments

Popular posts from this blog

twig - Using Twigbridge in a Laravel 5.1 Package -

jdbc - Not able to establish database connection in eclipse -

Kivy: Swiping (Carousel & ScreenManager) -