public async Task <string> GetED2KHash() { if (_hashString != null) { return(_hashString); } var queue = MaxSimultaneousChunks <= 0 ? new BlockingCollection <Task <Tuple <MD4Digest, bool> > >( new ConcurrentQueue <Task <Tuple <MD4Digest, bool> > >()) : new BlockingCollection <Task <Tuple <MD4Digest, bool> > >( new ConcurrentQueue <Task <Tuple <MD4Digest, bool> > >(), MaxSimultaneousChunks); Task.Run(() => { var fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read); for (uint i = 0; i < ChunkCount; i++) { byte[] data = new byte[fs.Length - fs.Position > ChunkSize ? ChunkSize : fs.Length - fs.Position]; fs.Read(data, 0, data.Length); var last = fs.Position == fs.Length; var index = i; Debug.Print("=>" + index); queue.Add(Task.Run(() => { Debug.Print("<=" + index); using (var chunk = new Chunk(data, last)) return(Tuple.Create(chunk.Digest(), chunk.Last)); })); ReadChunks = i + 1; } }); uint completedChunks = 0; MD4Context md4Context = new MD4Context(); Task <Tuple <MD4Digest, bool> > currentChunk; do { currentChunk = queue.Take(); var chunkHash = (await currentChunk).Item1.ToArray(); md4Context.Update(chunkHash, 0, chunkHash.Length); completedChunks++; CompletedChunks = completedChunks; } while (!currentChunk.Result.Item2); //While not last _hashString = md4Context.GetDigest().ToString(); return(_hashString); }
public void CalculateHash() { Complete = 0; MD4Context md4Context = new MD4Context(); if (ChunkCount == 1) { byte[] data = new byte[_fileStream.Length]; _fileStream.Read(data, 0, data.Length); Chunk newChunk = new Chunk(data); newChunk.CalculateHash(); _hash = newChunk.MD4Digest.ToString(); Complete = 1; return; } Parallel.Invoke(new Action[] { () => { for (int i = 0; i < ChunkCount; i++) { byte[] data = new byte[_fileStream.Length - _fileStream.Position > ChunkSize ? ChunkSize : _fileStream.Length - _fileStream.Position]; _fileStream.Read(data, 0, data.Length); Chunk newChunk = new Chunk(data) { Last = _fileStream.Position == _fileStream.Length }; ThreadPool.QueueUserWorkItem(o => newChunk.CalculateHash()); //Blocks if the queue is full _processQueue.Add(newChunk); } }, () => { Chunk currentChunk; do { //Blocks if the queue is empty currentChunk = _processQueue.Take(); //Blocks if the chunk hash is still calculating currentChunk.Done.WaitOne(); byte[] chunkHash = currentChunk.MD4Digest.ToArray(); md4Context.Update(chunkHash, 0, chunkHash.Length); Complete++; } while (!currentChunk.Last); } }); _hash = md4Context.GetDigest().ToString(); }