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
Post a Comment