title: DeflateStream.ReadAsync (.NET 4.5 System.IO.Compression) has different return value of bytes read than equivalent Read method?
body: <p>While converting some older code to use async in c#, I started seeing problems in variations of return values from the Read() and ReadAsync() methods of the DeflateStream.</p>
  
  <p>I thought that the transition from synchronous code like</p>
  
  <p><code>bytesRead = deflateStream.Read(buffer, 0, uncompressedSize);</code> </p>
  
  <p>to it's equivalent asynchronous version of </p>
  
  <p><code>bytesRead = await deflateStream.ReadAsync(buffer, 0, uncompressedSize);</code></p>
  
  <p>should always return the same value.</p>
  
  <hr>
  
  <p><strong>See updated code added to bottom of question - that uses streams the correct way - hence making the initial question irrelevant</strong></p>
  
  <hr>
  
  <p>I found that after number of iterations this didn't hold true, and in my specific case was causing random errors in the converted application.</p>
  
  <p>Am I missing something here?</p>
  
  <p>Below is simple repro case (in a console app), where the <code>Assert</code> will break for me in the <code>ReadAsync</code> method on iteration #412, giving output that looks like this:</p>
  
  <pre><code>....
  ReadAsync #410 - 2055 bytes read
  ReadAsync #411 - 2055 bytes read
  ReadAsync #412 - 453 bytes read
  ---- DEBUG ASSERTION FAILED ----
  </code></pre>
  
  <p>My question is, why is the <code>DeflateStream.ReadAsync</code> method returning 453 bytes at this point?</p>
  
  <p>Note: this only happens with certain input strings - the massive <code>StringBuilder</code> stuff in the <code>CreateProblemDataString</code> was the best way I could think of constructing the string for this post.</p>
  
  <pre><code>class Program
  {
      static byte[] DataAsByteArray;
      static int uncompressedSize;
  
      static void Main(string[] args)
      {
          string problemDataString = CreateProblemDataString();
          DataAsByteArray = Encoding.ASCII.GetBytes(problemDataString);
          uncompressedSize = DataAsByteArray.Length;
          MemoryStream memoryStream = new MemoryStream();
          using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress, true))
          {
              for (int i = 0; i &lt; 1000; i++)
              {
                  deflateStream.Write(DataAsByteArray, 0, uncompressedSize);
              }
          }
  
          // now read it back synchronously
          Read(memoryStream);
  
          // now read it back asynchronously
          Task retval = ReadAsync(memoryStream);
          retval.Wait();
      }
  
      static void Read(MemoryStream memoryStream)
      {
          memoryStream.Position = 0;
          using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Decompress, true))
          {
              byte[] buffer = new byte[uncompressedSize];
              int bytesRead = -1;
              int i = 0;
              while (bytesRead &gt; 0 || bytesRead == -1)
              {
                  bytesRead = deflateStream.Read(buffer, 0, uncompressedSize);
                  System.Diagnostics.Debug.WriteLine("Read #{0} - {1} bytes read", i, bytesRead);
                  System.Diagnostics.Debug.Assert(bytesRead == 0 || bytesRead == uncompressedSize);
                  i++;
              }
          }
      }
  
      static async Task ReadAsync(MemoryStream memoryStream)
      {
          memoryStream.Position = 0;
          using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Decompress, true))
          {
              byte[] buffer = new byte[uncompressedSize];
              int bytesRead = -1;
              int i = 0;
              while (bytesRead &gt; 0 || bytesRead == -1)
              {
                  bytesRead = await deflateStream.ReadAsync(buffer, 0, uncompressedSize);
                  System.Diagnostics.Debug.WriteLine("ReadAsync #{0} - {1} bytes read", i, bytesRead);
                  System.Diagnostics.Debug.Assert(bytesRead == 0 || bytesRead == uncompressedSize);
                  i++;
              }
          }
      }
  
      /// &lt;summary&gt;
      /// This is one of the strings of data that was causing issues. 
      /// &lt;/summary&gt;
      /// &lt;returns&gt;&lt;/returns&gt;
      static string CreateProblemDataString()
      {
          StringBuilder sb = new StringBuilder();
          sb.Append("0601051081                                      ");
          sb.Append("                                                                       ");
          sb.Append("                         225021         0300420");
          sb.Append("34056064070072076361102   13115016017");
          sb.Append("5      192         230237260250   2722");
          sb.Append("73280296      326329332   34535535");
          sb.Append("7   3                                                                  ");
          sb.Append("                                                                    4");
          sb.Append("                                                                             ");
          sb.Append("                                                         50");
          sb.Append("6020009      030034045   063071076   360102   13");
          sb.Append("1152176160170   208206      23023726025825027227328");
          sb.Append("2283285   320321333335341355357   622005009      0");
          sb.Append("34053      060070      361096   130151176174178172208");
          sb.Append("210198   235237257258256275276280290293   3293");
          sb.Append("30334   344348350                                                     ");
          sb.Append("                                                         ");
          sb.Append("                                           ");
          sb.Append("                                                                                   ");
          sb.Append("                                     225020012014   046042044034061");
          sb.Append("075078   361098   131152176160170   208195210   230");
          sb.Append("231260257258271272283306      331332336   3443483");
          sb.Append("54    29                                                           ");
          sb.Append("                                                                      ");
          sb.Append("                                                   2");
          sb.Append("5      29                                                06      0");
          sb.Append("1                                                            178      17");
          sb.Append("4                                                   205                     2");
          sb.Append("05      195                                                   2");
          sb.Append("31                     231      23");
          sb.Append("7                                       01              01    0");
          sb.Append("2                                              260                     26");
          sb.Append("2                                                            274                     2");
          sb.Append("72      274                                       01              01    0");
          sb.Append("3           1   5      3 6     43 52    ");
          return sb.ToString();
      }
  }
  </code></pre>
  
  <hr>
  
  <p><strong>UPDATED CODE TO READ STREAMS INTO BUFFER CORRECTLY</strong></p>
  
  <p>Output now looks like this:</p>
  
  <pre><code>...
  ReadAsync #410 - 2055 bytes read
  ReadAsync #411 - 2055 bytes read
  ReadAsync PARTIAL #412 - 453 bytes read, offset for next read = 453
  ReadAsync #412 - 1602 bytes read
  ReadAsync #413 - 2055 bytes read
  ...
  
  
  static void Read(MemoryStream memoryStream)
      {
          memoryStream.Position = 0;
          using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Decompress, true))
          {
              byte[] buffer = new byte[uncompressedSize]; // buffer to hold known fixed size record.
              int bytesRead; // number of bytes read from Read operation
              int offset = 0; // offset for writing into buffer
              int i = -1; // counter to track iteration #
              while ((bytesRead = deflateStream.Read(buffer, offset, uncompressedSize - offset)) &gt; 0)
              {
                  offset += bytesRead;  // offset in buffer for results of next reading
                  System.Diagnostics.Debug.Assert(offset &lt;= uncompressedSize, "should never happen - because would mean more bytes read than requested.");
                  if (offset == uncompressedSize) // buffer full, complete fixed size record in buffer.
                  {
                      offset = 0; // buffer is now filled, next read to start at beginning of buffer again.
                      i++; // increment counter that tracks iteration #
                      System.Diagnostics.Debug.WriteLine("Read #{0} - {1} bytes read", i, bytesRead);
                  }
                  else // buffer still not full
                  {
                      System.Diagnostics.Debug.WriteLine("Read PARTIAL #{0} - {1} bytes read, offset for next read = {2}", i+1, bytesRead, offset);
                  }
              }
          }
      }
  
      static async Task ReadAsync(MemoryStream memoryStream)
      {
          memoryStream.Position = 0;
          using (DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Decompress, true))
          {
              byte[] buffer = new byte[uncompressedSize]; // buffer to hold known fixed size record.
              int bytesRead; // number of bytes read from Read operation
              int offset = 0; // offset for writing into buffer
              int i = -1; // counter to track iteration #
              while ((bytesRead = await deflateStream.ReadAsync(buffer, offset, uncompressedSize - offset)) &gt; 0)
              {
                  offset += bytesRead;  // offset in buffer for results of next reading
                  System.Diagnostics.Debug.Assert(offset &lt;= uncompressedSize, "should never happen - because would mean more bytes read than requested.");
                  if (offset == uncompressedSize) // buffer full, complete fixed size record in buffer.
                  {
                      offset = 0; // buffer is now filled, next read to start at beginning of buffer again.
                      i++; // increment counter that tracks iteration #
                      System.Diagnostics.Debug.WriteLine("ReadAsync #{0} - {1} bytes read", i, bytesRead);
                  }
                  else // buffer still not full
                  {
                      System.Diagnostics.Debug.WriteLine("ReadAsync PARTIAL #{0} - {1} bytes read, offset for next read = {2}", i+1, bytesRead, offset);
                  }
              }
          }
      }
  </code></pre>