public void Find() { _targetFileHashDict.Clear(); _destinationFileHashDict.Clear(); _matches = new ConcurrentBag <FileMatch>(); // ReSharper disable AccessToForEachVariableInClosure foreach (var destinationFilePair in _destination.Files) { Parallel.ForEach( _target.Files, targetFilePair => { if (destinationFilePair.Value != targetFilePair.Value) { return; } byte[] destinationChunk = FirstChunk(destinationFilePair.Key, destinationFilePair.Value); byte[] targetChunk = FirstChunk(targetFilePair.Key, targetFilePair.Value); if (!ArrayUtil.ArraysEqual(destinationChunk, targetChunk)) { return; } IHashFunction hash = null; byte[] destinationHash; if (!_destinationFileHashDict.TryGetValue(destinationFilePair.Key, out destinationHash)) { hash = CreateMurmurHash3(); destinationHash = ComputeHash(destinationFilePair.Key, hash); _destinationFileHashDict.TryAdd(destinationFilePair.Key, destinationHash); } byte[] targetHash; if (!_targetFileHashDict.TryGetValue(targetFilePair.Key, out targetHash)) { if (hash == null) { hash = CreateMurmurHash3(); } targetHash = ComputeHash(targetFilePair.Key, hash); _targetFileHashDict.TryAdd(targetFilePair.Key, targetHash); } if (!ArrayUtil.ArraysEqual(destinationHash, targetHash)) { return; } _matches.Add(new FileMatch(targetFilePair.Key, destinationFilePair.Key)); }); } // ReSharper restore AccessToForEachVariableInClosure }