private async Task ProcessPoint(IFrame point) { IFrame result = new Frame() { Timestamp = Ticks.AlignToMicrosecondDistribution(point.Timestamp, FramesPerSecond), Published = point.Published, Measurements = point.Measurements }; Task <ITimeSeriesValue[]>[] analytics = m_analyticProcesors.Select(p => p.Run(point, m_futureFrameBuffer.ToArray())).ToArray(); await Task.WhenAll(analytics).ConfigureAwait(false); int i = 0; foreach (Task <ITimeSeriesValue[]> analyticResult in analytics) { m_analyticProcesors[i].RouteOutput(point, analyticResult.Result); i++; } m_queueOutput.Writer.TryWrite(result); }
private async void GetData(CancellationToken cancelationToken) { try { m_Source.MessageRecieved += ProcessMessage; int count = 0; if (!m_Source.SupportProgress) { ProgressArgs args = new ProgressArgs("This DataSource does not support Progress updates.", false, (int)50); ReportProgress?.Invoke(this, args); } await foreach (IFrame frame in m_Source.GetData(m_sourceSignals, m_start, m_end)) { frame.Timestamp = Ticks.AlignToMicrosecondDistribution(frame.Timestamp, m_commonFrameRate); await m_sourceQueue.Writer.WriteAsync(frame, cancelationToken); count++; if (count % 1000 == 0 && m_Source.SupportProgress) { ReportDatasourceProgress(m_Source.GetProgress()); } } } finally { MessageRecieved?.Invoke(this, new MessageArgs("Finished Loading Data from DataSource", MessageArgs.MessageLevel.Info)); m_sourceQueue.Writer.Complete(); } }
/// <summary> /// Starts the Process of computing any analytics. /// </summary> /// <param name="cancellationToken"></param> /// <returns></returns> public Task StartProcessor(CancellationToken cancellationToken) { return(Task.Run(async() => { try { IFrame point; m_futureFrameBuffer = new Queue <IFrame>(m_futureFrameBufferSize + 1); int nPoints = 0; Gemstone.Ticks lastProcessed = Ticks.MinValue; while (await m_queueInput.Reader.WaitToReadAsync(cancellationToken)) { if (!m_queueInput.Reader.TryRead(out point)) { continue; } // Tolerance withing a few Ticks of expected TimeStamp Ticks aligned = Ticks.AlignToMicrosecondDistribution(point.Timestamp, FramesPerSecond); long diff = aligned - point.Timestamp; if (diff > Ticks.PerMillisecond || diff < -Ticks.PerMillisecond) { continue; } // Generate Timestamps in between if necessary while (aligned - (m_lastProcessedTS + (long)(Ticks.PerSecond * (1.0D / (double)FramesPerSecond))) > (long)(Ticks.PerSecond * (0.5D / (double)FramesPerSecond)) && m_lastProcessedTS != Ticks.MinValue) { m_lastProcessedTS = m_lastProcessedTS + (long)(Ticks.PerSecond * (1.0D / (double)FramesPerSecond)); IFrame frame = new Frame() { Timestamp = Ticks.AlignToMicrosecondDistribution(m_lastProcessedTS, FramesPerSecond), Published = point.Published, Measurements = new ConcurrentDictionary <string, ITimeSeriesValue>() }; lastProcessed = frame.Timestamp; nPoints++; m_futureFrameBuffer.Enqueue(frame); if (nPoints <= m_futureFrameBufferSize) { continue; } frame = m_futureFrameBuffer.Dequeue(); await ProcessPoint(frame); } nPoints++; lastProcessed = point.Timestamp; m_futureFrameBuffer.Enqueue(point); if (nPoints <= m_futureFrameBufferSize) { continue; } point = m_futureFrameBuffer.Dequeue(); m_lastProcessedTS = aligned; await ProcessPoint(point); } // Run through the last set of Points int i = 0; while (i < m_futureFrameBuffer.Count) { point = m_futureFrameBuffer.Dequeue(); lastProcessed = point.Timestamp; await ProcessPoint(point); i++; } Task[] analyticCleanups = m_analyticProcesors.Select(p => p.RunCleanup(lastProcessed)).ToArray(); await Task.WhenAll(analyticCleanups).ConfigureAwait(false); int j = 0; IFrame cleanupFrame = new Frame() { Measurements = new ConcurrentDictionary <string, ITimeSeriesValue>(), Published = false, Timestamp = Ticks.MaxValue }; foreach (Task <ITimeSeriesValue[]> analyticResult in analyticCleanups) { m_analyticProcesors[j].RouteOutput(cleanupFrame, analyticResult.Result); j++; } m_queueOutput.Writer.TryWrite(cleanupFrame); Complete(); } catch (Exception ex) { int T = 1; } }, cancellationToken)); }