Генерация сигнатуры файла. Потеря памяти - C#
Формулировка задачи:
Нужно написать программу, которая будет генерировать сигнатуру. Файл делим на заданные блоки и их хэшируем ( hash-функции SHA256), и вместе с номером блока выводим в консоль. Нужно чтобы программа могла обработать файлы, размер которых больше озу. При работе с потоками допускается использовать только стандартные классы и библиотеки из .Net 3.5 (исключая ThreadPool, BackgroundWorker, TPL).
Проблема заключается в том что периодически вылетает программа при этом пишет что очередь пуста. Понимаю что косяк скорее с событиями, но не могли бы вы подсказать как можно было бы реализовать это.
И ещё проблема с огромными затратами памяти, как реализовать чтобы по экономичнее вышло и не вылетало если размер файла больше озу
namespace Signature
{
class GenericSignature
{
int _numProcs;
long _blockSize;
long _blockCount;
long _fileSize;
string _path;
Queue<byte[]> _queueBlockFile;
private EventWaitHandle _eventBlockRead;
public GenericSignature(string path, int size)
{
_blockSize = size;
_path = path;
_blockCount = 0;
_queueBlockFile = new Queue<byte[]>();
_eventBlockRead = new EventWaitHandle(false, EventResetMode.AutoReset);
}
public void signatureCreate()
{
try
{
_numProcs = Environment.ProcessorCount;
ThreadStart read = new ThreadStart(readFile);
ThreadStart hash = new ThreadStart(hashCreate);
Thread readThread = new Thread(read);
Thread hashThread = new Thread(hash);
readThread.Start();
hashThread.Start();
readThread.Join();
hashThread.Join();
}
catch (Exception e)
{
Console.WriteLine(e);
Console.WriteLine(e.StackTrace);
}
}
private void readFile()
{
byte[] portion;
try
{
using (FileStream sourceStream = new FileStream(_path, FileMode.Open))
{
_fileSize = sourceStream.Length;
_blockCount = sourceStream.Length / _blockSize;
for (int i = 0; i <= _blockCount; i++)
{
if (i == _blockCount)
portion = new byte[_fileSize - _blockSize * i];
else
portion = new byte[_blockSize];
sourceStream.Read(portion, 0, portion.Length);
Monitor.Enter(_queueBlockFile);
_queueBlockFile.Enqueue(portion);
Monitor.Exit(_queueBlockFile);
_eventBlockRead.Set();
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
Console.WriteLine(e.StackTrace);
}
}
private void hashCreate()
{
//try
//{
byte[] portion;
SHA256 sha = SHA256Managed.Create();
byte[] hash;
_eventBlockRead.WaitOne();
for (int i = 0; i <= _blockCount; i++)
{
Monitor.Enter(_queueBlockFile);
while (_queueBlockFile.Count == 0)
{
Thread.Sleep(10);
}
portion = _queueBlockFile.Dequeue();
Monitor.Exit(_queueBlockFile);
if (portion == null)
{
_eventBlockRead.WaitOne();
}
else
{
hash = sha.ComputeHash(portion);
Console.WriteLine("блок {0}", i, BitConverter.ToString(hash));
}
}
/*}
catch (Exception e)
{
Console.WriteLine(e);
Console.WriteLine(e.StackTrace);
}*/
}
}
class Program
{
static void Main(string[] args)
{
string inPath = @"E://batalon.mkv";//сделать ввод из консоли!!!
int sizeBlock = 100000;
GenericSignature sig = new GenericSignature(inPath, sizeBlock);
sig.signatureCreate();
}
}
}Решение задачи: «Генерация сигнатуры файла. Потеря памяти»
textual
Листинг программы
private void readFile()
{
byte[] portion;
try
{
using (FileStream sourceStream = new FileStream(_path, FileMode.Open))
{
_fileSize = sourceStream.Length;
_blockCount = sourceStream.Length / _blockSize;
for (int i = 0; i <= _blockCount; i++)
{
if (i == _blockCount)
portion = new byte[_fileSize - _blockSize * i];
else
portion = new byte[_blockSize];
sourceStream.Read(portion, 0, portion.Length);
bool full;
do
{
Monitor.Enter(_queueBlockFile);
full = _queueBlockFile.Count >= 16;
Monitor.Exit(_queueBlockFile);
if (full)
Thread.Sleep(10);
} while (full);
Monitor.Enter(_queueBlockFile);
_queueBlockFile.Enqueue(portion);
Monitor.Exit(_queueBlockFile);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
Console.WriteLine(e.StackTrace);
}
}
private void hashCreate()
{
SHA256 sha = SHA256Managed.Create();
for (int i = 0; i <= _blockCount; i++)
{
bool empty;
do
{
Monitor.Enter(_queueBlockFile);
empty = _queueBlockFile.Count == 0;
Monitor.Exit(_queueBlockFile);
if (empty)
Thread.Sleep(10);
} while (empty);
Monitor.Enter(_queueBlockFile);
byte[] portion = _queueBlockFile.Dequeue();
Monitor.Exit(_queueBlockFile);
byte[] hash = sha.ComputeHash(portion);
Console.WriteLine("блок {0}: {1}", i, BitConverter.ToString(hash));
}
}