/// <summary>
        /// Checks for markers whose position has been reached or left.
        /// </summary>
        public void CheckMarkerPositions(TimeSpan mediaPosition, MediaMarkerCollection <TMediaMarker> markers, bool seeking = false, bool ignoreSearchWindow = false)
        {
            lock (_syncObject)
            {
                // clean up any previously active markers that are no longer in the markers list
                PreviouslyActiveMarkers.ToList()
                .Where(i => !markers.Contains(i))
                .ForEach(OnMarkerLeft)
                .ForEach(i => PreviouslyActiveMarkers.Remove(i));

                //Safeguard against large unusual position changes
                if (!seeking && PreviousPosition.HasValue)
                {
                    var rangeStart = PreviousPosition.Value < mediaPosition ? PreviousPosition.Value : mediaPosition;
                    var rangeEnd   = PreviousPosition.Value > mediaPosition ? PreviousPosition.Value : mediaPosition;

                    seeking = rangeEnd.Subtract(rangeStart) > LargestNormalStepSize;
                }

                IList <TMediaMarker> activeMarkers;
                var searchAfter = SeekingSearchWindow.HasValue && !ignoreSearchWindow
                                        ? mediaPosition.Subtract(SeekingSearchWindow.Value)
                                        : (TimeSpan?)null;

                if (!seeking && PreviousPosition.HasValue)
                {
                    var rangeStart = PreviousPosition.Value < mediaPosition ? PreviousPosition.Value : mediaPosition;
                    var rangeEnd   = PreviousPosition.Value > mediaPosition ? PreviousPosition.Value : mediaPosition;
                    activeMarkers = markers.WhereActiveInRange(rangeStart, rangeEnd, searchAfter).ToList();
                }
                else
                {
                    activeMarkers = markers.WhereActiveAtPosition(mediaPosition, searchAfter).ToList();
                }


                PreviouslyActiveMarkers.Where(i => !i.IsActiveAtPosition(mediaPosition))
                .ForEach(OnMarkerLeft)
                .ForEach(i => activeMarkers.Remove(i));

                activeMarkers.Where(i => !PreviousPosition.HasValue || !PreviouslyActiveMarkers.Contains(i))
                .ForEach(i => OnMarkerReached(i, seeking));

                PreviouslyActiveMarkers = PreviouslyActiveMarkers.Where(i => i.IsActiveAtPosition(mediaPosition) && !activeMarkers.Contains(i))
                                          .Concat(activeMarkers)
                                          .ToList();
                PreviousPosition = mediaPosition;
            }
        }
        public void CheckMarkerPosition(TimeSpan mediaPosition, TMediaMarker marker, bool seeking = false)
        {
            lock (_syncObject)
            {
                bool isActive = false;

                if (!seeking && PreviousPosition.HasValue)
                {
                    var rangeStart = PreviousPosition.Value < mediaPosition ? PreviousPosition.Value : mediaPosition;
                    var rangeEnd   = PreviousPosition.Value > mediaPosition ? PreviousPosition.Value : mediaPosition;
                    isActive = marker.IsActiveInRange(rangeStart, rangeEnd);
                }
                else
                {
                    isActive = marker.IsActiveAtPosition(mediaPosition);
                }

                if (isActive && (!PreviousPosition.HasValue || !PreviouslyActiveMarkers.Contains(marker)))
                {
                    OnMarkerReached(marker, seeking);
                    PreviouslyActiveMarkers.Add(marker);
                }
            }
        }