/// <summary> /// Called on a background thread for when this node is ACTUALLY polling /// This is not called if we're not due for a poll when the pass runs /// </summary> private void InnerPoll(bool force = false) { var sw = Stopwatch.StartNew(); try { if (Polling != null) { var ps = new PollStartArgs(); Polling(this, ps); if (ps.AbortPoll) { return; } } var polled = 0; Parallel.ForEach(DataPollers, i => { var pollerResult = i.Poll(force); Interlocked.Add(ref polled, pollerResult); }); LastPoll = DateTime.UtcNow; if (Polled != null) { Polled(this, new PollResultArgs { Polled = polled }); } if (FirstPollRun != null) { FirstPollRun.Set(); FirstPollRun = null; } Interlocked.Add(ref _totalCachePolls, polled); Interlocked.Increment(ref _totalPolls); } finally { sw.Stop(); LastPollDuration = sw.Elapsed; _isPolling = false; _pollTask = null; } }
public virtual async Task PollAsync(bool force = false) { using (MiniProfiler.Current.Step("Poll - " + UniqueKey)) { // If not forced, perform our "should-run" checks if (!force && !NeedsPoll) { return; } // Prevent multiple poll threads for this node from running at once if (Interlocked.CompareExchange(ref _isPolling, 1, 0) != 0) { // We're already running, abort!' // TODO: Date check for sanity and restart? return; } PollStatus = "Poll Started"; CurrentPollDuration = Stopwatch.StartNew(); try { PollStatus = "InnerPoll Started"; if (Polling != null) { var ps = new PollStartArgs(); Polling(this, ps); if (ps.AbortPoll) { return; } } PollStatus = "DataPollers Queueing"; var tasks = new List <Task>(); foreach (var p in DataPollers) { if (force || p.ShouldPoll) { tasks.Add(p.PollGenericAsync(force)); } } // Hop out early, run nothing else if (tasks.Count == 0) { PollStatus = "DataPollers Complete (None to run)"; return; } PollStatus = "DataPollers Queued (Now awaiting)"; // Await all children (this itself will be a background fire and forget if desired await Task.WhenAll(tasks).ConfigureAwait(false); PollStatus = "DataPollers Complete (Awaited)"; LastPoll = DateTime.UtcNow; Polled?.Invoke(this, new PollResultArgs()); Interlocked.Increment(ref _totalPolls); } finally { Interlocked.Exchange(ref _isPolling, 0); if (CurrentPollDuration != null) { CurrentPollDuration.Stop(); LastPollDuration = CurrentPollDuration.Elapsed; } CurrentPollDuration = null; } PollStatus = "Poll Complete"; } }
/// <summary> /// Called on a background thread for when this node is ACTUALLY polling /// This is not called if we're not due for a poll when the pass runs /// </summary> private void InnerPollImpl(bool force = false, bool sync = false) { CurrentPollDuration = Stopwatch.StartNew(); try { PollStatus = "InnerPoll Started"; if (Polling != null) { var ps = new PollStartArgs(); Polling(this, ps); if (ps.AbortPoll) { return; } } int toPoll = 0; if (sync || FirstPollRun != null) { PollStatus = "DataPollers Queueing (Sync)"; var tasks = DataPollers .Where(p => force || p.ShouldPoll) .Select(p => p.PollAsync(force)) .ToArray <Task>(); Task.WaitAll(tasks); PollStatus = "DataPollers Complete (Sync)"; } else { PollStatus = "DataPollers Queueing"; foreach (var p in DataPollers) { // Cheap checks to eliminate many uncessary task creations if (!force && !p.ShouldPoll) { continue; } // Kick off the poll and don't wait for it to continue; #pragma warning disable 4014 p.PollStatus = "Kicked off by Node"; Interlocked.Add(ref _totalCacheQueues, 1); p.PollAsync(force).ContinueWith(t => { if (t.IsFaulted) { Current.LogException(t.Exception); PollStatus = "Faulted"; } else { PollStatus = "Completed"; } Interlocked.Add(ref _totalCachePolls, t.Result); }, TaskContinuationOptions.ExecuteSynchronously).ConfigureAwait(false); toPoll++; #pragma warning restore 4014 } PollStatus = toPoll.ToComma() + " DataPollers Started"; } LastPoll = DateTime.UtcNow; Polled?.Invoke(this, new PollResultArgs { Queued = toPoll }); if (FirstPollRun != null) { FirstPollRun.Set(); FirstPollRun = null; } Interlocked.Increment(ref _totalPolls); } finally { CurrentPollDuration.Stop(); LastPollDuration = CurrentPollDuration.Elapsed; _isPolling = false; CurrentPollDuration = null; PollStatus = "InnerPoll Complete"; } }