並列キャッシュを構築しようとしています。要件は、一度に起動する必要があるn個の datacollector があることです。これらのデータ コレクターはそれぞれ、境界層 (これをサービス層と呼びます) に到達し、データを取得します。ただし、これは同じ要求 (WCF) 内にあるため、2 つのデータ コレクターがサービス層で同じメソッドを呼び出す必要がある場合、最初の要求が完了するまで 2 番目の要求を待機させたくありません。
これは、データ コレクターを構築する開発者に対して透過的に構築する必要があります (Unity Interception を使用して、このキャッシング アスペクトを挿入します)。
フローは次のようになります。Reactive 拡張機能は、この種の設計に適していますか? 私は過去に Rx を扱ったことがなく、開発の 10 日後にレンガの壁にぶつかりたくありません。それ以外の場合は、async、await、およびイベントの組み合わせもここでうまく機能する可能性があります。
編集: Rx を使用してこれを実装しました - マルチスレッドのコンテキストでうまく機能します。興味深いのは、tryGet の代わりに add を試したことです。(これは Unity インターセプト CallHandler です)
/// <summary>
/// Intercepts the calls and tries to retrieve from the cache
/// </summary>
class CacheCallHandler : ICallHandler
{
[Dependency]
public ICache RequestCache { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
IMethodReturn mesg = null;
string cacheKey = CacheKeyGenerator.GetCacheKey(input);
//create the task to retrieve the data
var task = new Task<IMethodReturn>(() =>
{
return getNext()(input, getNext);
});
//make it observable
var observableItem = task.ToObservable();
//try to add it to the cache
//we need to do this in the order of Add and then try to get, otherwise multiple thread might enter the same area
if (RequestCache.TryAdd(cacheKey, observableItem))
{
//if the add succeeed, it means that we are responsible to starting this task
task.Start();
}
else
{
if ( RequestCache.TryGetValue(cacheKey, out observableItem) )
{
//do nothing, the observable item is already updated with the requried reference
}
else
{
throw new CacheHandlerException("Could not add to cache AND could not retrieve from cache either. Something's wrong", input);
}
}
//observe the return
if ( observableItem != null )
mesg = observableItem.FirstOrDefault();
if (mesg == null)
throw new CacheHandlerException("Not return value found. this should not happen", input);
return mesg;
}
/// <summary>
/// Should always be the first to execute on the boundary
/// </summary>
public int Order
{
get { return 1; }
set { ; }
}
}