public void Run() { foreach (long blockNum in this.listOfBlocks) { this.fileReader.SeekToBlock(blockNum); byte[] origChunk = fileReader.ReadNextBlock(); this.OrigChunkLength = origChunk.Length; this.GzippedChunk = GzipWrapper.CompressBlock(origChunk); // Suspend to wait for main thread. this.WaitHandlerFromMainThread.Reset(); // Notify main thread that gzippedChunk is ready for dump. this.WaitHandlerTowardsMainThread.Set(); // Wait for main thread to set the handler after dumping. this.WaitHandlerFromMainThread.WaitOne(); } }
static int Main(string[] args) { ArgumentsCaptor argumentsCaptor; try { argumentsCaptor = new ArgumentsCaptor(args); } catch (ArgumentException ex) { Console.WriteLine(ex.Message); if (ex.InnerException != null) { Console.WriteLine(ex.InnerException); } Console.WriteLine(""); PrintUsage("GZipTest.exe"); return(1); } string command = argumentsCaptor.Command; string origFileName = argumentsCaptor.OrigFileName; string resFileName = argumentsCaptor.ResFileName; try { switch (command) { case "compress": { FileInfo fileInfo = new FileInfo(origFileName); long amountOfBlocks = fileInfo.Length.DivideRoundUp(argumentsCaptor.BlockSize); List <long>[] distributedBlocksByThreads = WorkDistributor.DistributeWork(amountOfBlocks, argumentsCaptor.NumOfThreads); CompressingThread[] threadObjs = new CompressingThread[distributedBlocksByThreads.Length]; Thread[] threads = new Thread[distributedBlocksByThreads.Length]; if (argumentsCaptor.IsVerbose) { Console.WriteLine($"Blocks amount: {amountOfBlocks}"); Console.WriteLine("Distributed by threads:"); } for (int i = 0; i < distributedBlocksByThreads.Length; ++i) { if (argumentsCaptor.IsVerbose) { Console.WriteLine($"Thread {i}: " + string.Join(", ", distributedBlocksByThreads[i].ToArray())); } threadObjs[i] = new CompressingThread(origFileName, distributedBlocksByThreads[i], argumentsCaptor.BlockSize); threads[i] = new Thread(new ThreadStart(threadObjs[i].Run)); } using (PackedSerializer fileWriter = new PackedSerializer(resFileName)) { // Start all threads. for (int i = 0; i < threads.Length; ++i) { threads[i].Start(); } int numOfRunningThreads; do { numOfRunningThreads = 0; // Wait for all threads to prepare gzipped chunks. for (int i = 0; i < threads.Length; ++i) { if (threads[i].IsAlive) { if (argumentsCaptor.IsVerbose) { Console.WriteLine($"Thread {i} is alive..."); } ++numOfRunningThreads; } else { if (argumentsCaptor.IsVerbose) { Console.WriteLine($"Thread {i} died."); } continue; } if (argumentsCaptor.IsVerbose) { Console.WriteLine($"Thread {i}: waiting..."); } threadObjs[i].WaitHandlerTowardsMainThread.WaitOne(); // According to the algorithm which distributed the work // we have a guarantee here that we can sequentially write gzipped chunks. if (argumentsCaptor.IsVerbose) { Console.WriteLine($"Thread {i}: gzipped."); } fileWriter.WriteGzippedChunk(threadObjs[i].GzippedChunk, threadObjs[i].OrigChunkLength); // Let the thread to go on. We'll come to it again later when time comes. if (argumentsCaptor.IsVerbose) { Console.WriteLine($"Thread {i}: letting go."); } threadObjs[i].WaitHandlerTowardsMainThread.Reset(); threadObjs[i].WaitHandlerFromMainThread.Set(); } if (argumentsCaptor.IsVerbose) { Console.WriteLine($"Alive threads: {numOfRunningThreads}"); } } while (numOfRunningThreads > 0); } } break; case "decompress": { try { using (PackedDeserializer fileReader = new PackedDeserializer(origFileName)) using (FileStream fileWriter = File.Create(resFileName)) { while (fileReader.IsNextBlockAvailable()) { byte[] packedChunk = fileReader.ReadNextPackedChunk(out int origLength); byte[] unpackedChunk = GzipWrapper.DecompressBlock(packedChunk, origLength); fileWriter.Write(unpackedChunk, 0, unpackedChunk.Length); } fileWriter.Flush(); } } catch (InvalidDataException ex) { Console.WriteLine("Corrupted archive. Unfortunately there is probably nothing you can fix :("); Console.WriteLine("Just for a case we provide tech info below:"); Console.WriteLine(ex); return(1); } } break; default: Console.WriteLine($"Unknown command: {command}!"); PrintUsage("GZipTest.exe"); return(1); } } catch (FileNotFoundException ex) { Console.WriteLine($"Cannot locate file: {ex.FileName}."); return(1); } catch (UnauthorizedAccessException ex) { Console.WriteLine($"Access denied."); Console.WriteLine("Information below might help you to understand the cause:"); Console.WriteLine(ex); return(1); } catch (IOException ex) { Console.WriteLine("Error occured during reading or writing file."); Console.WriteLine("Information below might help you to understand the cause:"); Console.WriteLine(ex); return(1); } return(0); }