private void ProcessDownloads() { if (Interlocked.Exchange(ref _isProcessDownloads, 1) == 1) { return; } while (_incomingBlocks.TryDequeue(out var incomingBlock)) { Torrent.WriteBlock(incomingBlock.Piece, incomingBlock.Block, incomingBlock.Data); } if (Torrent.IsCompleted) { Interlocked.Exchange(ref _isProcessDownloads, 0); return; } int[] ranked = GetRankedPieces(); foreach (var piece in ranked) { if (Torrent.IsPieceVerified[piece]) { continue; } foreach (var peer in GetRankedSeeders()) { if (!peer.IsPieceDownloaded[piece]) { continue; } // just request blocks in order for (int block = 0; block < Torrent.GetBlockCount(piece); block++) { if (_downloadThrottle.IsThrottled) { continue; } if (Torrent.IsBlockAcquired[piece][block]) { continue; } // only request one block from each peer at a time if (peer.BlocksRequested > 0) { continue; } // only request from 1 peer at a time if (Peers.Count(x => x.Value.IsBlockRequested[piece][block]) > 0) { continue; } int size = Torrent.GetBlockSize(piece, block); peer.SendRequest(piece, block * Torrent.BlockSize, size); _downloadThrottle.Add(size); peer.IsBlockRequested[piece][block] = true; } } } Interlocked.Exchange(ref _isProcessDownloads, 0); }