/// <summary>
        /// Processes all pages, computing checksums to determine chunks of virtual pages that have changed
        /// </summary>
        private void ProcessPages()
        {
            // Check for newly allocated pages
            lock (this.ChunkLock)
            {
                foreach (RegionProperties newPage in this.CollectNewPages())
                {
                    this.ChunkList.AddFirst(newPage);
                }
            }

            Int32 chunkLimit;

            if (this.IsTaskComplete)
            {
                chunkLimit = ChunkLinkedListPrefilter.ChunkLimit;
            }
            else
            {
                chunkLimit = ChunkLinkedListPrefilter.RampUpChunkLimit;
            }

            lock (this.ChunkLock)
            {
                // Process the allowed amount of chunks from the priority queue
                Parallel.For(
                    0,
                    Math.Min(this.ChunkList.Count, chunkLimit),
                    SettingsViewModel.GetInstance().ParallelSettings,
                    index =>
                {
                    RegionProperties chunk;
                    Boolean success = false;

                    // Grab next available element
                    lock (this.ElementLock)
                    {
                        chunk = this.ChunkList.FirstOrDefault();

                        if (chunk == null)
                        {
                            return;
                        }

                        this.ChunkList.RemoveFirst();

                        // Do not process chunks that have been marked as changed
                        if (chunk.HasChanged)
                        {
                            this.ChunkList.AddLast(chunk);
                            return;
                        }
                    }

                    // Read current page data for chunk
                    Byte[] pageData = EngineCore.GetInstance().OperatingSystemAdapter?.ReadBytes(chunk.BaseAddress, chunk.RegionSize, out success);

                    // Read failed; Deallocated page
                    if (!success)
                    {
                        return;
                    }

                    // Update chunk
                    chunk.Update(pageData);

                    // Recycle it
                    lock (this.ElementLock)
                    {
                        ChunkList.AddLast(chunk);
                    }
                });
            }
        }