/// <summary> /// Считывает часть данных из файла и помещает ее в очередь. /// </summary> /// <param name="obj">Поток, который работает с данным методом (класса ManualThread)</param> /// <exception cref="ArgumentException">Если аргумент метода не является объектом класса ManualThread</exception> private void ReadDataPart(object obj) { if (!(obj is ManualThread)) { throw new ArgumentException("Метод чтения данных требует объект класса ManualThread"); } ManualThread worker = obj as ManualThread; byte[] buffer = new byte[PartSize]; long fileLength = inputStream.BaseStream.Length; ulong totalRam = Options.GetTotalRAM(); while (fileLength > 0) { ulong ram = Options.GetAvailableRAMInBytes(); if (ram < (uint)(PartSize * NumThreads) || ram < (totalRam / 100.0) * swapBoundary) { Thread.Sleep(10); if (queue.Count == 0) { GC.Collect(); } continue; } int numBytes = inputStream.Read(buffer, 0, PartSize); if (numBytes == 0) { break; } byte[] realPart = null; try { realPart = new byte[numBytes]; } catch (OutOfMemoryException) { GC.Collect(); if (IsWorkInProgress()) { while(queue.Count > 0) { Thread.Sleep(100); } } realPart = new byte[numBytes]; } Array.Copy(buffer, realPart, numBytes); queue.Enqueue(new NumberedPart(partIndex, realPart)); partIndex++; } worker.Complete(); }
/// <summary> /// Выполняет извлечение части данных из очереди, шифрует их с помощью SHA256 и выводит в стандартный поток вывода /// </summary> /// <param name="obj">Поток, который работает с даннным методом (класса ManualThread)</param> /// <exception cref="ArgumentException">Если аргумент метода не является объектом класса ManualThread</exception> /// <exception cref="InvalidOperationException">Если в очереди был объект класса типа, отличного от NumberedPart</exception> private void ConvertToSHA(object obj) { if (!(obj is ManualThread)) { throw new ArgumentException("Метод шифрования требует объект класса ManualThread"); } ManualThread worker = obj as ManualThread; while (true) { if (queue.Count == 0) { if (!reader.IsWorkCompleted) { continue; } else { worker.Complete(); break; } } else { NumberedPart part = null; lock (dequeueSync) { if (queue.Count > 0) { var tempPart = queue.Dequeue(); if (tempPart is NumberedPart) { part = tempPart as NumberedPart; } else { throw new InvalidOperationException("В очередь попал объект класса, отличающийся от NumberedPart"); } } } if (part != null) { Console.WriteLine($"Часть № {part.Number}\n{Sha256(part.Data)}\n"); } } } }
public SHAConverter(Options options) { PartSize = options.PartSize; FileName = options.Filename; inputStream = new BinaryReader(new FileStream(options.Filename, FileMode.Open, FileAccess.Read, FileShare.Read)); NumThreads = options.NumThreads; reader = new ManualThread(new Thread(ReadDataPart)); for (int i = 0; i < NumThreads; i++) { ManualThread worker = new ManualThread(new Thread(ConvertToSHA)); workers.Add(worker); } }