/// <summary> /// Uses list func to fetch fresh data on the instances in the predicate. /// Instances that fail the condition are enqueued for the next pass. /// </summary> /// <returns></returns> internal async Task CallListAndProcessResults() { // extract the predicate that restricts the list call string predicate = _odataFilterSB.ToString(); // clear the sb for the next batch _odataFilterSB.Clear(); // early exit if there is no work to do if (string.IsNullOrWhiteSpace(predicate)) { return; } // update the detail level _odataDetailLevel.FilterClause = predicate; // get the enumerable to refresh the instances IPagedEnumerable <T> tEnumberable = _listObjects(); // get the enumerator for asycn walk of the collection IPagedEnumerator <T> tEnumerator = tEnumberable.GetPagedEnumerator(); // used to enumerate until out of data bool thereIsMoreData; do { // move to next instance, possibley make call to server to get next batch Task <bool> asyncTask = tEnumerator.MoveNextAsync(this.CancellationToken); thereIsMoreData = await asyncTask.ConfigureAwait(continueOnCapturedContext : false); if (thereIsMoreData) { // get the current instance T refreshedInstance = tEnumerator.Current; // test it to see if it is done if (!_condition(refreshedInstance)) { // we will have to refresh it again so put in queue for next pass // box it up MonitorLastCall <T> mlc = new MonitorLastCall <T>(refreshedInstance, DateTime.UtcNow + _odataMonitorControl.DelayBetweenDataFetch); // enqueue it for next pass this.NextPassQueue.Enqueue(mlc); } } }while (thereIsMoreData); }
/// <summary> /// Iterates over an <see cref="IPagedEnumerable{T}"/> sequence, invoking a synchronous delegate for each element. /// </summary> /// <param name="source">The <see cref="IPagedEnumerable{T}"/> to iterate over.</param> /// <param name="body">The delegate to execute for each element in <paramref name="source"/>.</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> for controlling the lifetime of the asynchronous operation.</param> /// <returns>A <see cref="System.Threading.Tasks.Task"/> that represents the iteration operation. The task /// completes when iteration is complete.</returns> /// <remarks>This method processes elements sequentially, not concurrently. That is, for each element in the /// sequence, the method completes execution of the delegate before processing the next element.</remarks> public static async Task ForEachAsync <T>(this IPagedEnumerable <T> source, Action <T> body, CancellationToken cancellationToken = default(CancellationToken)) { if (source == null) { throw new ArgumentNullException("source"); } if (body == null) { throw new ArgumentNullException("body"); } using (IPagedEnumerator <T> enumerator = source.GetPagedEnumerator()) { while (await enumerator.MoveNextAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { cancellationToken.ThrowIfCancellationRequested(); body(enumerator.Current); } } }