/// <summary> /// Invoke underlying batch operation with aggregating. /// </summary> public async Task <IReadOnlyList <TResult> > InvokeAsync(IReadOnlyList <TArg> args) { ProxyItem <TArg, TResult> proxyItem; int startIndex; if (!TryAggregate(args, out proxyItem, out startIndex)) { proxyItem = new ProxyItem <TArg, TResult>(args); _aggregatableQueue.TryAdd(proxyItem, null); startIndex = 0; _pool.Queue(async() => { object _; _aggregatableQueue.TryRemove(proxyItem, out _); proxyItem.Close(); try { proxyItem.TaskCompletionSource.SetResult(await _func(proxyItem.Args)); } catch (Exception ex) { proxyItem.TaskCompletionSource.SetException(ex); } }); } var results = await proxyItem.TaskCompletionSource.Task; await Task.Yield(); return((IReadOnlyList <TResult>) new Segment <TResult>(results, startIndex, args.Count)); }
private bool TryAggregate( IReadOnlyList <TArg> args, out ProxyItem <TArg, TResult> proxyItem, out int startIndex) { foreach (var item in _aggregatableQueue) { var current = item.Key; startIndex = current.TryAggregate(args, _rules); if (startIndex != -1) { proxyItem = current; return(true); } } // unable to aggregate proxyItem = null; startIndex = -1; return(false); }