【问题标题】:Write and read from a stream asynchronously异步写入和读取流
【发布时间】:2021-08-11 15:23:49
【问题描述】:

我想异步写入和读取流。我正在使用 GCP 的存储 API,特别是 StorageClient.DownloadObjectAsync。它需要一个被写入的流。我想将写入该流的字节传递给我正在调用的另一个 API。

我正在苦苦挣扎的是阅读,因为它似乎流(MemoryStream 在这种情况下)不支持同时阅读和写作。还有其他选择吗?

这里是相关的sn-ps:

下载器

using (StorageClient sc = StorageClient.Create(cred))
{
    await sc.DownloadObjectAsync(
        "841f1487-d1b3-434d-8848-8a4bb0749b20",
        @"filename",
        stream);
}

作家

// Use a BinaryReader?
using BinaryReader br = new BinaryReader(stream);
int current = 0;
int total = 0;
do
{
    current = br.Read(buffer, 0, buffer.Length);
    if (current > 0)
    {
        fileStore.WriteFile(out int numberOfBytesWritten, directoryHandle, total, buffer);
        total += current;
    }
} while (current > 0)

编辑 - 添加附加信息

当我在文件下载时尝试读取时,在 BinaryReader 停止读取之前我只获得 1% 的字节,即使文件已完全在内存中(虽然此文件可以放入内存,但并非所有文件都将能够)。

【问题讨论】:

  • 这段代码是如何运行的?你怎么知道流不支持同时读写,会发生什么?您提供的细节越多,我们就越容易发现哪里出了问题
  • 计划是两个有两个线程,一个用于写作,一个用于阅读。当我在文件下载时尝试读取时,即使文件完全在内存中,在 BinaryReader 停止读取之前我也只能获得 1% 的字节(虽然此文件可以放入内存,但并非所有文件都可以) .

标签: c# stream


【解决方案1】:

还有其他选择吗?

代码当前正在下载到内存流,然后将其写入磁盘。如果您只需要这样做,那么传递文件流而不是内存流就足够了。

我正在苦苦挣扎的是阅读,因为似乎流(在本例中为 MemoryStream)不支持同时读写。

这是正确的。没有内置流类型支持同时读取和写入。一个原因是存在一个单一“位置”的概念,它通过读取和写入来更新。

应该可以写一个并发流类型。您需要处理并发访问以及拥有两个位置而不是一个位置,并且并发流可能不支持某些操作。我曾多次考虑编写这样的类型,但在 PipelinesChannelsDataflowasync streams 已经存在的世界中,我觉得它不够有用。

所以,我想说:

  1. 如果可能,只需将文件流传递给它并完全摆脱内存流。
  2. 否则,请探索 GCP API,看看是否有可用于下载的非基于流的解决方案。
  3. 如果 GCP API必须下载到流中并且您的代码必须在保存期间进行内存处理,那么您将需要写一个并发流类型。

【讨论】:

  • 1.不幸的是,不能使用 FileStream。原因是应用程序在 Linux 上运行,目标是 SMB 共享,而 FileStream 不支持该方案。 2. 我做了一些查看,但非常了解这个实现。我会做更多的挖掘。 3. 以为我们必须走这条路,但想看看我是否遗漏了什么,因为我在这条路上找不到任何东西。谢谢!
  • 进一步考虑,我认为您真正想要的并发流是有 两个 流 - 一个只读和一个只写。流对将在幕后连接。
  • 我不确定 .NET 在 Linux 上是否支持这一点,但匿名命名管道本质上是做同样的事情:连接两个流。这可能是一个解决方案。
【解决方案2】:

终于找到我想要的了。答案是使用Pipe 类。

就像创建一个新管道 (Pipe pipe = new Pipe()) 一样简单,将下载器修改为采用 PipeWriter 而不仅仅是一个流,这样我就可以在写完后调用 pw.CompleteAsync()(你仍然可以使用pw.AsStream() 获取流,并使用pipe.Reader.AsStream() 传入PipeReader 流。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多