public async Task StartMonitoring(Task preTask) { _logger?.Info("{0} A ring is set up: {1}", m_host.FullName, DisplayName); await preTask.ConfigureAwait(false); _logger?.Info("{0} Ring pretask done. Starting check loop for {1}", m_host.FullName, DisplayName); while (true) { await Task.Delay(m_host.m_dataflowOptions.MonitorInterval).ConfigureAwait(false); bool empty = false; if (m_hb.NoHeartbeatDuring(() => { empty = this.IsRingEmpty(); }) && empty) { _logger.Debug("{0} 1st level empty ring check passed for {1}", m_host.FullName, this.DisplayName); bool noHeartbeat = await m_hb.NoHeartbeatDuring( async() => { //trigger batch foreach (var batchedFlow in m_ringNodes.OfType <IBatchedDataflow>()) { batchedFlow.TriggerBatch(); } await Task.Delay(m_host.m_dataflowOptions.MonitorInterval).ConfigureAwait(false); empty = this.IsRingEmpty(); }).ConfigureAwait(false); if (noHeartbeat && empty) { _logger.Debug("{0} 2nd level empty ring check passed for {1}", m_host.FullName, this.DisplayName); m_hb.Complete(); //start the completion domino :) break; } else { //batched flow dumped some hidden elements to the flow, go back to the loop _logger.Debug("{0} New elements entered the ring by batched flows ({1}). Will fall back to 1st level empty ring check.", m_host.FullName, this.DisplayName); } } } _logger.Info("{0} Ring completion detected! Completion triggered on heartbeat node: {1}", m_host.FullName, DisplayName); }