/// <summary> /// Work load for getting full sub-tree /// </summary> /// <param name="client">RingMasterClient object</param> /// <param name="token">Cancellation token</param> /// <param name="threadId">Thread sequence number</param> /// <returns>Async task</returns> private Task GetFullSubtreeThread(IRingMasterRequestHandler client, CancellationToken token, int threadId) { int taskCount = 0; var clock = Stopwatch.StartNew(); while (!token.IsCancellationRequested) { while (this.QueuedNodes.TryDequeue(out string path) && !token.IsCancellationRequested) { SpinWait.SpinUntil(() => taskCount < this.AsyncTaskCount || token.IsCancellationRequested); var startTime = clock.Elapsed; var task = client.GetFullSubtree(path, true) .ContinueWith( t => { Interlocked.Decrement(ref taskCount); if (t.Exception != null) { this.IncrementTotalFailures(); this.Log($"Failed to get full subtree on path {path}: {t.Exception.Message}"); } else { var children = t.Result.Children; this.AddTotalDataSize(children.Sum(c => c.Data.Length)); this.IncrementTotalDataCount(children.Count); var duration = (clock.Elapsed - startTime).TotalMilliseconds; MdmHelper.LogOperationDuration((long)duration, OperationType.GetFullSubtree); } }); Interlocked.Increment(ref taskCount); this.QueuedNodes.Enqueue(path); } } SpinWait.SpinUntil(() => taskCount == 0); return(Task.FromResult(0)); }