I am trying to figure out how to write the compression and decompression process using GZip in a multi-threaded environment.
When unzipping a file in a multi-threaded environment, it constantly produces the following errors: StackOverFlow , System.OutOfMemory .
In debug mode on lines:
blockLength = BitConverter.ToInt32(lengthBuffer, 4); and
_dataSize = BitConverter.ToInt32(compressedData[i], blockLength - 4) in the second thread, cosmic variables are assigned, which lead to fatal errors. I tried to put 4 bytes, I was "played" in every way, trying to implement it in different ways. Outcome one. Please help !. Code below.
public abstract class GZip { protected static bool _cancelled = false; protected static bool _success = false; protected string sourceFile, destinationFile; protected static int _threads = Environment.ProcessorCount; protected const int buffer_size = 1024 * 1024; protected static int blockSize = 10000000; protected static byte[][] lastBuffer = new byte[_threads][]; protected static byte[][] compressedData = new byte[_threads][]; public GZip(string input, string output) { this.sourceFile = input; this.destinationFile = output; } public int CallBackResult() { if (!_cancelled && _success) return 0; return 1; } public void Cancel() { _cancelled = true; } public abstract void Launch(); } class Decompressor : GZip { public Decompressor(string input, string output) : base(input, output) { } public override void Launch() { Console.Write("Decompressing"); try { using (FileStream _compressedFile = new FileStream(sourceFile, FileMode.Open)) { using (FileStream _decompressedFile = new FileStream(sourceFile.Remove(sourceFile.Length - 3), FileMode.Append)) { int blockLength; int _dataSize; byte[] lengthBuffer = new byte[8]; Thread[] tPool = new Thread[_threads]; while (_compressedFile.Position < _compressedFile.Length) { for (int i = 0; (i < _threads) && (_compressedFile.Position < _compressedFile.Length); i++) { Console.Write("."); _compressedFile.Read(lengthBuffer, 0, lengthBuffer.Length); blockLength = BitConverter.ToInt32(lengthBuffer, 4); compressedData[i] = new byte[blockLength]; lengthBuffer.CopyTo(compressedData[i], 0); _compressedFile.Read(compressedData[i], 8, blockLength - 8); _dataSize = BitConverter.ToInt32(compressedData[i], blockLength - 4); lastBuffer[i] = new byte[_dataSize]; tPool[i] = new Thread(Decompress); tPool[i].Start(i); } for (int i = 0; (i < _threads) && (tPool[i] != null);) { if (tPool[i].ThreadState == ThreadState.Stopped) { _decompressedFile.Write(lastBuffer[i], 0, lastBuffer[i].Length); i++; } } } } } } catch (Exception ex) { Console.WriteLine("Error is occured!\n Method: {0}\n Error description {1}", ex.TargetSite, ex.Message); _cancelled = true; } } public static void Decompress(object i) { using (MemoryStream _memoryStream = new MemoryStream(compressedData[(int)i])) { using (GZipStream cs = new GZipStream(_memoryStream, CompressionMode.Decompress)) { cs.Read(lastBuffer[(int)i], 0, lastBuffer[(int)i].Length); } } } } }
Thread.Join- Pavel Mayorov method