public void Run(Func <Stream> getSrcStream, Func <Stream> getDstStream, int blockLength)
 {
     if (IsRunning)
     {
         return;
     }
     IsRunning = true;
     new Thread(() =>
     {
         GetSourceStream      = getSrcStream;
         GetDestinationStream = getDstStream;
         _blockLength         = blockLength;
         Exception exception  = null;
         _readThread          = ThreadHelper.RunGuarded(ReadThreadFunction, (ex) =>
         {
             _isCanceled = true;
             exception   = ex;
         });
         _writeThread = ThreadHelper.RunGuarded(WriteThreadFunction, (ex) =>
         {
             _isCanceled = true;
             exception   = ex;
         });
         _processThreads = new Thread[Environment.ProcessorCount];
         for (int i = 0; i < _processThreads.Length; i++)
         {
             _processThreads[i] = ThreadHelper.RunGuarded(ProcessThreadFunction, (ex) =>
             {
                 _isCanceled = true;
                 exception   = ex;
             });
         }
         ThreadHelper.WaitThreads(_readThread);
         _readQueue.Close();
         ThreadHelper.WaitThreads(_processThreads);
         _writeQueue.Close();
         ThreadHelper.WaitThreads(_writeThread);
         CompressionResultType crType = CompressionResultType.Success;
         if (exception == null)
         {
             crType = _isCanceled ? CompressionResultType.Cancelled : CompressionResultType.Success;
         }
         else
         {
             crType = CompressionResultType.Fail;
         }
         IsRunning = false;
         ProcessingFinished?.Invoke(this, new CompressionResult(crType, exception));
     }).Start();
 }
 public CompressionResult(CompressionResultType type, Exception exception)
 {
     Type      = type;
     Exception = exception;
 }