c# - 迁移到异步 : Repository

标签 c# repository async-await .net-4.5

我有一个大型代码库使用我的存储库,它们都实现了 IRespository,并且我正在实现这些方法的异步版本:

T Find(id);
Task<T> FindAsync(id);
...etc...

有几种存储库。最简单的是基于一个不可变的集合,其中实体的范围足够小,值得一次从数据库中加载它们。此加载发生在任何人第一次调用任何 IRepository 方法时。例如,Find(4) 将在加载尚未发生时触发加载。

我已经用 Lazy < T > 实现了这个。非常方便,已经工作多年。

我不能在 Async 上使用冷火鸡,所以我必须在同步版本旁边添加 Async。我的问题是,我不知道先调用哪个 - 存储库上的同步或异步方法。

我不知道如何声明我的懒惰 - 如果我像往常一样这样做,

Lazy<MyCollection<T>> 

然后当首先调用 FindAsync() 时加载它不会是异步的。另一方面,如果我去

Lazy<Task<MyCollection<T>>>

这对于 FindAsync() 非常有用,但是同步方法如何触发初始加载而不与 Cleary 先生关于调用 Task.Result 的死锁警告发生冲突?

感谢您的宝贵时间!

最佳答案

Lazy<T> 的问题是只有一种工厂方法。如果第一次调用是同步的,你真正想要的是一个同步工厂方法,如果第一次调用是异步的,你真正想要的是一个异步工厂方法。 Lazy<T>不会为你做那件事,而且 AFAIK 也没有其他内置的东西可以提供这些语义。

但是,您可以自己构建一个:

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);
  }
}

或者你可以只使用这个模式而不封装它:

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();
}

“bool sync”模式是 Stephen Toub 最近向我展示的一个模式。据我所知,目前还没有博客或任何关于它的内容。

关于c# - 迁移到异步 : Repository,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30946315/

相关文章:

android - shell脚本envsetup.sh是如何执行launch的?

javascript - 让 Knex.js 事务与 ES7 async/await 一起使用

c# - 用于 Android 预处理器宏的 Mono

c# - ASP.NET 网络应用程序 : Unable to read DLL

git - Bare 和非 Bare 存储库之间的实际区别是什么?

linux - 如何查找包含某个包的存储库

typescript - 如何正确处理 Vuejs 中异步事件监听器中的拒绝错误?

node.js - Node.js 中异步/等待的行为

c# - 在单向 WCF 调用后调用服务代理 block 上的 Close()

c# - Spidermonkey - 从 C# 或 C++ (VIsual Studio 2010) 调用 javascript 函数