private void OnSerialDataReceived(object sender, SerialDataReceivedEventArgs e) { // Bare minimum while (_sp.BytesToRead <= 5) { Thread.Sleep(1); } _sp.Read(_inBuf, 0, 5); // Not an RC data frame, or 0-length data if (_inBuf[4] != 105 || _inBuf[3] <= 0) { _sp.DiscardInBuffer(); return; } // Await full data payload while (_sp.BytesToRead < _inBuf[3] + 1) { Thread.Sleep(1); } _sp.Read(_inBuf, 5, _sp.BytesToRead); if (_axes == null) { _axes = new Axis[_inBuf[3] / 2]; for (int i = 0; i < _axes.Length; i++) { _axes[i] = new Axis(i + 1); } AxesSetup?.Invoke(this, new EventArgs()); } SetValues(); Polled?.Invoke(this, new EventArgs()); }
/// <summary> /// Start the indefinitely long polling task. It is ran in LongRunning mode which ends up creating a new separate thread for the task. /// </summary> /// <returns>The task containing the polling calls</returns> public Task StartPolling() { IsRunning = true; return(Task.Factory.StartNew(() => { do { var jobStatus = _wpsClient.GetJobStatus(_wpsUri, JobId).Result; switch (jobStatus.Status) { case JobStatus.Running: if (jobStatus.NextPollDateTime.HasValue) { _nextPoll = jobStatus.NextPollDateTime.Value; } else { _nextPoll = DateTime.Now + TimeSpan.FromSeconds(DefaultNextPollInterval); } _lastPoll = DateTime.Now; Polled?.Invoke(this, new SessionPolledEventArgs(DateTime.Now, _nextPoll)); break; case JobStatus.Succeeded: var result = _wpsClient.GetResult <TData>(_wpsUri, JobId).Result; Finished?.Invoke(this, new SessionFinishedEventArgs <TData>(result)); _cancellationTokenSource.Cancel(); break; case JobStatus.Failed: var exceptionReport = _wpsClient.GetExceptionForRequest(_wpsUri, new GetResultRequest { JobId = JobId }).Result; Failed?.Invoke(this, new SessionFailedEventArgs(exceptionReport)); _cancellationTokenSource.Cancel(); break; } if (!_cancellationTokenSource.IsCancellationRequested) { if (_nextPoll > _lastPoll) { Task.Delay(_nextPoll - _lastPoll).Wait(); } } } while (!_cancellationTokenSource.Token.IsCancellationRequested); IsRunning = false; }, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Current)); }
/// <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; Polled?.Invoke(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"; } }