/// <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); } }); } }