views:

288

answers:

1

Suppose I have a chain of streams, that does Compression -> Encryption -> File I/O.

In C#, using synchronous I/O, it would look something like this:

  int n=0;
  byte[] buffer= new byte[2048];
  string inputFileName = "input.txt";
  string outputFileName = inputFileName + ".compressed.encrypted";
  using (FileStream inputFileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read))
  {
      using (FileStream outputFileStream = File.Open(outputFileName, FileMode.Create, FileAccess.ReadWrite))
      {
          using (Stream encryptor = new EncryptingStream(fs))
          {
              using (Stream compressor = new CompressorStream(encryptor))
              {
                  while ((n = inputFileStream.Read(buffer, 0, buffer.Length)) > 0)
                  {
                      compressor.Write(buffer, 0, n);
                  }
              }
          }
      }
  }

To take advantage of the async I/O offered by the FileStream, I suppose I cannot simply use the BeginWrite() method on the compressor stream.

In this example, in order to take advantage of async I/O on FileStream, I think that the EncryptingStream would need to implement Write by calling BeginWrite/EndWrite on the wrapped Stream. If the wrapped Stream is a FileStream, then I'd get the asynch I/O. Is that correct?

+2  A: 

Calling BeginWrite on the outer stream (here, compressor) will successfully move the work onto the thread pool, thus causing it to execute asynchronously with respect to the calling method. This will probably be adequate for your application, but it is not the maximum possible efficiency. As you point out, BeginWrite would not be used on the inner FileStream which is actually performing the disk I/O. When BeginWrite is used there, FileStream's implementation of BeginWrite takes advantage of the "Windows completion port API" which provides higher scalability.

Another way to look at this is from the point of view of the operating system, it will not be asynchronous I/O. However, it will run synchronously on a thread pool thread, effectively making it asynchronous to all of your other code. To really take advantage of the operating system asynchronous I/O, you need to call BeginWrite on a class that can use the completion port API.

I'm not sure exactly what compression you are using, so take this with a grain of salt. For example, the Stream you are using might not even implement BeginWrite or it might implement it synchronously.

binarycoder