public void Handler(ref TaskPool readerTaskPool, ref TaskPool writerTaskPool) { int blockNumber = -1; byte[] blockValue = null; while (true) { try { if (!readerTaskPool.TryGet(out blockNumber, out blockValue)) { return; } if (blockValue == null) { break; } byte[] compressedBlock = GZip.Compress(blockValue); if (!writerTaskPool.TrySet(blockNumber, compressedBlock)) { return; } } catch (Exception e) { _isDelete = true; Terminate(); Console.WriteLine(e.Message); return; } } }
static void Main(string[] args) { ParseArgs options; try { options = new ParseArgs(args); } catch (Exception e) { Console.WriteLine(e.Message); return; } ICommand Command = null; ProgressReport progress; if (options.Command == Operation.Compress) { Command = new Compressor(); progress = new ProgressReport("Compress"); } else { Command = new Decompressor(); progress = new ProgressReport("Decompress"); } _readerTaskPool = new TaskPool(_cores); _writerTaskPool = new TaskPool(_cores); Stopwatch sw = new Stopwatch(); sw.Start(); Command.ShowProgress += progress.ShowProgress; Command.Terminate += _readerTaskPool.Terminate; Command.Terminate += _writerTaskPool.Terminate; _reader = new Thread(delegate() { Command.Reader(options.Source, ref _readerTaskPool); }); for (int i = 0; i < _cores; i++) { _handlers[i] = new Thread(delegate() { Command.Handler(ref _readerTaskPool, ref _writerTaskPool); }); } _writer = new Thread(delegate() { Command.Writer(options.Destination, ref _writerTaskPool); }); _reader.Start(); foreach (Thread handler in _handlers) { handler.Start(); } _writer.Start(); _writer.Join(); foreach (Thread handler in _handlers) { handler.Join(); } _reader.Join(); sw.Stop(); progress.Done(sw.Elapsed); Command.Terminate -= _writerTaskPool.Terminate; Command.Terminate -= _readerTaskPool.Terminate; Command.ShowProgress -= progress.ShowProgress; }
public void Writer(string destination, ref TaskPool writerTaskPool) { int counter = 0; int blockNumber = -1; byte[] blockValue = null; try { using (BinaryWriter bw = new BinaryWriter(new FileStream(destination, FileMode.Create, FileAccess.Write, FileShare.None))) { bw.Write(BitConverter.GetBytes(_sourceLength)); bw.Write(BitConverter.GetBytes(_blockCount)); while (true) { if (!writerTaskPool.TryGet(out blockNumber, out blockValue)) { return; } if (blockValue == null) { break; } try { bw.Write(BitConverter.GetBytes(blockNumber)); bw.Write(blockValue.Length); bw.Write(blockValue); } catch (IOException e) { Terminate(); Console.WriteLine("ERROR: операция прервана ({0})", e.Message); bw.Close(); File.Delete(destination); return; } counter++; ShowProgress((double)counter / _blockCount); if (counter == _blockCount) { Terminate(); } } } } catch (Exception e) { _isDelete = true; Terminate(); Console.WriteLine(e.Message); } if (_isDelete) { try { File.Delete(destination); } catch (Exception e) { Console.WriteLine(e.Message); return; } } }
public void Writer(string destination, ref TaskPool writerTaskPool) { try { FileInfo fi = new FileInfo(destination); DriveInfo drive = new DriveInfo(fi.Directory.Root.FullName); if (drive.DriveFormat == "FAT32" && _originLength > FAT32_MAX_FILE_SIZE) { throw new IOException("ERROR: недостаточно места на диске записи распакованного файла (ограничение FAT32)"); } } catch (Exception e) { Terminate(); Console.WriteLine(e.Message); return; } int counter = 0; int blockNumber = -1; byte[] blockValue = null; Dictionary <int, byte[]> buffer = new Dictionary <int, byte[]>(); try { using (BinaryWriter bw = new BinaryWriter(new FileStream(destination, FileMode.Create, FileAccess.Write, FileShare.None))) { while (true) { if (!writerTaskPool.TryGet(out blockNumber, out blockValue)) { return; } if (blockValue == null) { break; } buffer[blockNumber] = blockValue; while (buffer.ContainsKey(counter)) { bw.Write(buffer[counter]); buffer.Remove(counter); counter++; ShowProgress((double)counter / _blockCount); if (counter == _blockCount) { Terminate(); return; } } } } } catch (Exception e) { _isDelete = true; Terminate(); Console.WriteLine(e.Message); } if (_isDelete) { try { File.Delete(destination); } catch (Exception e) { Console.WriteLine(e.Message); return; } } }