/// <summary>
        /// Performs a seek operation to the specified position.
        /// </summary>
        /// <param name="position">The position.</param>
        private void Seek(TimeSpan position)
        {
            SeekingDone.Wait();
            var startTime   = DateTime.UtcNow;
            var resumeClock = Clock.IsRunning;

            Clock.Pause();

            SeekingDone.Reset();
            PacketReadingCycle.Wait();
            FrameDecodingCycle.Wait();
            BlockRenderingCycle.Wait();

            // Clear Blocks and frames, reset the render times
            foreach (var t in Container.Components.MediaTypes)
            {
                Frames[t].Clear();
                Blocks[t].Clear();
                LastRenderTime[t] = TimeSpan.MinValue;
            }

            // Populate frame with after-seek operation
            var frames = Container.Seek(position);

            foreach (var frame in frames)
            {
                Frames[frame.MediaType].Push(frame);
            }

            // Resume the clock if it was running before the seek operation
            OnPropertyChanged(nameof(Position));
            if (resumeClock)
            {
                Clock.Play();
            }

            Container.Log(MediaLogMessageType.Debug,
                          $"SEEK D: Elapsed: {startTime.DebugElapsedUtc()}");

            RequestedSeekPosition = null;
            SeekingDone.Set();
        }
        public async Task CloseAsync()
        {
            Container?.Log(MediaLogMessageType.Debug, $"{nameof(CloseAsync)}: Entered");
            Clock.Pause();

            IsTaskCancellationPending = true;

            // Wait for cycles to complete.
            await Task.Run(() =>
            {
                while (!BlockRenderingCycle.Wait(1))
                {
                }
                while (!FrameDecodingCycle.Wait(1))
                {
                }
                while (!PacketReadingCycle.Wait(1))
                {
                }
            });

            BlockRenderingTask?.Join();
            FrameDecodingTask?.Join();
            PacketReadingTask?.Join();

            BlockRenderingTask = null;
            FrameDecodingTask  = null;
            PacketReadingTask  = null;

            foreach (var renderer in Renderers.Values)
            {
                renderer.Close();
            }

            Renderers.Clear();

            // Reset the clock
            Clock.Reset();

            Container?.Log(MediaLogMessageType.Debug, $"{nameof(CloseAsync)}: Completed");

            // Dispose the container
            if (Container != null)
            {
                Container.Dispose();
                Container = null;
            }

            // Dispose the Blocks for all components
            foreach (var kvp in Blocks)
            {
                kvp.Value.Dispose();
            }
            Blocks.Clear();

            // Dispose the Frames for all components
            foreach (var kvp in Frames)
            {
                kvp.Value.Dispose();
            }
            Frames.Clear();

            // Clear the render times
            LastRenderTime.Clear();

            // Update notification properties
            UpdateMediaProperties();
            MediaState = MediaState.Close;
        }