}  // Dispose

#if !NETFX_CORE
        public override IAsyncResult BeginWrite(byte[] array, int offset, int count, AsyncCallback asyncCallback, object asyncState) {

            EnsureCompressionMode();            

            // We use this checking order for compat to earlier versions:
            if (asyncOperations != 0 )
                throw new InvalidOperationException(SR.GetString(SR.InvalidBeginCall));

            ValidateParameters(array, offset, count);
            EnsureNotDisposed();
           
            Interlocked.Increment(ref asyncOperations);

            try {                

                DeflateStreamAsyncResult userResult = new DeflateStreamAsyncResult(
                                                            this, asyncState, asyncCallback, array, offset, count);
                userResult.isWrite = true;

                m_AsyncWriterDelegate.BeginInvoke(array, offset, count, true, m_CallBack, userResult);
                userResult.m_CompletedSynchronously &= userResult.IsCompleted;            
                                
                return userResult;

            } catch {
                Interlocked.Decrement(ref asyncOperations);
                throw;
            }
        }
        private void AwaitAsyncResultCompletion(DeflateStreamAsyncResult asyncResult) {

            try {

                if (!asyncResult.IsCompleted)
                    asyncResult.AsyncWaitHandle.WaitOne();

            } finally {

                Interlocked.Decrement(ref asyncOperations);
                asyncResult.Close();  // this will just close the wait handle
            }
        }
        public override IAsyncResult BeginRead(byte[] array, int offset, int count, AsyncCallback asyncCallback, object asyncState) {
            
            EnsureDecompressionMode();

            // We use this checking order for compat to earlier versions:
            if (asyncOperations != 0)
                throw new InvalidOperationException(SR.GetString(SR.InvalidBeginCall));

            ValidateParameters(array, offset, count);
            EnsureNotDisposed();                       

            Interlocked.Increment(ref asyncOperations);

            try {                

                DeflateStreamAsyncResult userResult = new DeflateStreamAsyncResult(
                                                            this, asyncState, asyncCallback, array, offset, count);
                userResult.isWrite = false;

                // Try to read decompressed data in output buffer
                int bytesRead = inflater.Inflate(array, offset, count);
                if( bytesRead != 0) {
                    // If decompression output buffer is not empty, return immediately.
                    // 'true' means we complete synchronously.
                    userResult.InvokeCallback(true, (object) bytesRead);                      
                    return userResult;
                }

                if (inflater.Finished() ) {  
                    // end of compression stream
                    userResult.InvokeCallback(true, (object) 0);  
                    return userResult;
                }
                    
                // If there is no data on the output buffer and we are not at 
                // the end of the stream, we need to get more data from the base stream
                _stream.BeginRead(buffer, 0, buffer.Length, m_CallBack, userResult);   
                userResult.m_CompletedSynchronously &= userResult.IsCompleted;            
                
                return userResult;

            } catch {
                Interlocked.Decrement( ref asyncOperations);
                throw;
            }
        }