/// <summary> /// Releases the unmanaged resources used by the <see cref="ConcentratorBase"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { if (m_publicationTimer != null) { m_publicationTimer.Tick -= PublishFrames; m_publicationTimer.Dispose(); } m_publicationTimer = null; if (m_frameQueue != null) { m_frameQueue.Dispose(); } m_frameQueue = null; if (m_monitorTimer != null) { m_monitorTimer.Elapsed -= MonitorUnpublishedSamples; m_monitorTimer.Dispose(); } m_monitorTimer = null; if (m_latestMeasurements != null) { m_latestMeasurements.Dispose(); } m_latestMeasurements = null; m_lastDiscardedMeasurement = null; } } finally { m_disposed = true; // Prevent duplicate dispose. } } }
private bool m_disposed; // Disposed flag detects redundant calls to dispose method #endregion #region [ Constructors ] /// <summary> /// Creates a new <see cref="ConcentratorBase"/>. /// </summary> /// <param name="framesPerSecond">Number of frames to publish per second.</param> /// <param name="lagTime">Past time deviation tolerance, in seconds - this becomes the amount of time to wait before publishing begins.</param> /// <param name="leadTime">Future time deviation tolerance, in seconds - this becomes the tolerated +/- accuracy of the local clock to real-time.</param> /// <remarks> /// <para> /// <paramref name="framesPerSecond"/> must be between 1 and 1000. /// </para> /// <para> /// <paramref name="lagTime"/> must be greater than zero, but can be specified in sub-second intervals (e.g., set to .25 for a quarter-second lag time). /// Note that this defines time sensitivity to past timestamps. /// </para> /// <para> /// <paramref name="leadTime"/> must be greater than zero, but can be specified in sub-second intervals (e.g., set to .5 for a half-second lead time). /// Note that this defines time sensitivity to future timestamps. /// </para> /// <para> /// Concentration will not begin until consumer "Starts" concentrator (i.e., calling <see cref="ConcentratorBase.Start"/> method or setting /// <c><see cref="ConcentratorBase.Enabled"/> = true</c>). /// </para> /// </remarks> /// <exception cref="ArgumentOutOfRangeException">Specified argument is outside of allowed value range (see remarks).</exception> protected ConcentratorBase(int framesPerSecond, double lagTime, double leadTime) { if (lagTime <= 0) throw new ArgumentOutOfRangeException("lagTime", "lagTime must be greater than zero, but it can be less than one"); if (leadTime <= 0) throw new ArgumentOutOfRangeException("leadTime", "leadTime must be greater than zero, but it can be less than one"); this.FramesPerSecond = framesPerSecond; #if UseHighResolutionTime m_realTimeTicks = PrecisionTimer.UtcNow.Ticks; #else m_realTime = DateTime.UtcNow.Ticks; #endif m_allowSortsByArrival = true; m_lagTime = lagTime; m_leadTime = leadTime; m_lagTicks = (long)(m_lagTime * Ticks.PerSecond); m_latestMeasurements = new ImmediateMeasurements(this); // Create a new queue for managing real-time frames m_frameQueue = new FrameQueue(this); // Create high precision timer used for frame processing m_publicationTimer = new PrecisionTimer(); m_publicationTimer.AutoReset = true; m_publicationTimer.Tick += PublishFrames; // This timer monitors the total number of unpublished samples every second. This is a useful statistic // to monitor: if total number of unpublished samples exceed lag time, measurement concentration could // be falling behind. m_monitorTimer = new System.Timers.Timer(); m_monitorTimer.Interval = 1000; m_monitorTimer.AutoReset = true; m_monitorTimer.Elapsed += MonitorUnpublishedSamples; }
private bool m_disposed; // Disposed flag detects redundant calls to dispose method #endregion #region [ Constructors ] /// <summary> /// Creates a new <see cref="ConcentratorBase"/>. /// </summary> /// <remarks> /// Concentration will not begin until consumer "Starts" concentrator (i.e., calling <see cref="ConcentratorBase.Start"/> method or setting /// <c><see cref="ConcentratorBase.Enabled"/> = true</c>). /// </remarks> protected ConcentratorBase() { #if UseHighResolutionTime m_realTimeTicks = PrecisionTimer.UtcNow.Ticks; #else m_realTime = DateTime.UtcNow.Ticks; #endif m_allowSortsByArrival = true; m_allowPreemptivePublishing = true; m_downsamplingMethod = DownsamplingMethod.LastReceived; m_latestMeasurements = new ImmediateMeasurements(this); // Create a new queue for managing real-time frames m_frameQueue = new FrameQueue(this.CreateNewFrame); // Set minimum timer resolution to one millisecond to improve timer accuracy PrecisionTimer.SetMinimumTimerResolution(1); // Create publication wait handle m_publicationWaitHandle = new AutoResetEvent(false); // Create publication thread - this may be one of the few times when you can // accurately argue that you need high priority thread scheduling... m_publicationThread = new Thread(PublishFrames); m_publicationThread.Priority = ThreadPriority.Highest; m_publicationThread.Start(); // This timer monitors the total number of unpublished samples every second. This is a useful statistic // to monitor: if total number of unpublished samples exceed lag time, measurement concentration could // be falling behind. m_monitorTimer = new System.Timers.Timer(); m_monitorTimer.Interval = 1000; m_monitorTimer.AutoReset = true; m_monitorTimer.Elapsed += MonitorUnpublishedSamples; }
// Protected Methods /// <summary>Shuts down concentrator in an orderly fashion.</summary> protected virtual void Dispose(bool disposing) { if (!m_disposed) { if (disposing) { if (m_publicationTimer != null) { m_publicationTimer.Tick -= PublishFrames; m_publicationTimer.Dispose(); } m_publicationTimer = null; if (m_frameQueue != null) { m_frameQueue.Dispose(); } m_frameQueue = null; if (m_monitorTimer != null) { m_monitorTimer.Elapsed -= MonitorUnpublishedSamples; m_monitorTimer.Dispose(); } m_monitorTimer = null; if (m_latestMeasurements != null) { m_latestMeasurements.Dispose(); } m_latestMeasurements = null; } } m_disposed = true; }
/// <summary> /// Releases the unmanaged resources used by the <see cref="ConcentratorBase"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { DetachFromFrameRateTimer(m_framesPerSecond); m_publicationThread = null; if (m_publicationWaitHandle != null) { AutoResetEvent publicationWaitHandle = m_publicationWaitHandle; m_publicationWaitHandle = null; publicationWaitHandle.Set(); publicationWaitHandle.Close(); } if (m_frameQueue != null) { m_frameQueue.Dispose(); } m_frameQueue = null; if (m_monitorTimer != null) { m_monitorTimer.Elapsed -= MonitorUnpublishedSamples; m_monitorTimer.Dispose(); } m_monitorTimer = null; if (m_latestMeasurements != null) { m_latestMeasurements.Dispose(); } m_latestMeasurements = null; m_lastDiscardedMeasurement = null; // Clear minimum timer resolution. PrecisionTimer.ClearMinimumTimerResolution(1); } } finally { m_disposed = true; // Prevent duplicate dispose. if (Disposed != null) Disposed(this, EventArgs.Empty); } } }