与 Lazy<T> 一起使用时如何从 MemoryCache 中识别和排除异常?

How to identify and expel exceptions from MemoryCache when used with Lazy<T>?

我正在使用 following pattern 和 MemoryCache:

public static T GetFromCache<T>(string key, Func<T> valueFactory) {
    var newValue = new Lazy<T>(valueFactory);
    var oldValue = (Lazy<T>)cache.AddOrGetExisting(key, newValue, new CacheItemPolicy());
    return (oldValue ?? newValue).Value;
}

并称它为:

var v = GetFromCache<Prop>(request.Key, () => LongCalc());

这很好用。但是,当 LongCalc 抛出异常时, cache.AddOrGetExisting 将异常保存到缓存中。

我试图通过以下方式确定何时发生:

if (oldValue != null && oldValue.Value.GetType() == typeof(Exception)) {
  cache.Remove(key, CacheEntryRemovedReason.Evicted);
}

但简单地调用 oldValue.Value 会引发异常。

如何判断oldValue对象是否存在异常并进行相应处理?

这是错误的做法。它永远不会与惰性评估一起工作,特别是如果您不得不将它提升到多线程环境一次。传递一个(理想情况下,纯 - 即无状态)回调 Action<Exception> 作为可选参数,并确保有合理但足够通用的默认实现。

或者,至少,提供您的自定义 ExceptionAwareLazy<T>,它将持有适当的标志。这样的解决方案会更糟糕,但是没有异步回调会打扰你。

P.S。 ReactiveExtensions 是我建议的方法的好例子。您可以轻松地将您的解决方案包装成 TaskCompletionSource 并坚持使用众所周知的 async/await.