使用流式传输的异步I/O(BeginWrite/BeginRead)有哪些影响?

3
假设我有一个流链,它执行压缩->加密->文件I/O操作。
在C#中,使用同步I/O,代码大概如下:
  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);
                  }
              }
          }
      }
  }

为了利用FileStream提供的异步I/O,我认为我不能简单地在压缩流上使用BeginWrite()方法。
在这个例子中,为了利用FileStream的异步I/O,我认为EncryptingStream需要通过调用包装流上的BeginWrite/EndWrite来实现Write。如果包装流是FileStream,则会得到异步I/O。这样理解是否正确?

你是在问如果最内层的流被调用了'BeginWrite'会发生什么? - pomeroy
1个回答

2
在外部流(这里是压缩器)上调用BeginWrite将成功地将工作移动到线程池中,从而使其与调用方法异步执行。这可能对您的应用程序来说已经足够了,但它并不是最大的效率。正如您所指出的,内部执行磁盘I/O的FileStream不会使用BeginWrite。当在那里使用BeginWrite时,FileStreamBeginWrite实现利用了“Windows完成端口API”,提供了更高的可扩展性。
从操作系统的角度来看,另一种看待它的方式是它不会是异步I/O。但是,它将在线程池线程上同步运行,有效地使其对您的所有其他代码异步。要真正利用操作系统的异步I/O,您需要在可以使用完成端口API的类上调用BeginWrite
我不确定您正在使用什么压缩方式,所以请谨慎对待这个问题。例如,您正在使用的Stream可能甚至没有实现BeginWrite,或者它可能是同步实现的。

1
听起来你在暗示最外层对BeginWrite的调用(例如compressor.BeginWrite)不会反过来调用代理流(例如EncryptingStream)上的BeginWrite,而是会调用encryptor.Write - pomeroy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接