【问题标题】:Using System.IO.Pipelines together with Stream将 System.IO.Pipelines 与 Stream 一起使用
【发布时间】:2018-12-16 11:10:06
【问题描述】:

我考虑在我们的应用程序中用 System.IO.Pipelines 替换基于 Stream 的 IO,以避免不必要的内存分配(首先考虑 RecyclableMemoryStream,但它似乎已停止使用)。但是在某些地方,由于外部库强加的接口,我仍然必须使用 Stream。所以我的 PipeWriter 需要将其数据包装在 Stream 中。

我没有找到关于这个主题的太多内容,但在另一个问题的答案中找到了使用装饰器模式 (C# Stream Pipe (Stream Spy)) 的建议。我不确定将 Pipelines 隐藏在 Stream 包装器后面是否是一种权利,但找不到其他任何东西可以让我将数据通过管道传输到流中。我错过了什么吗?

更新。下面是一个使用 SSH.NET 开源库将文件上传到 FTP 服务器 (https://gist.github.com/DavidDeSloovere/96f3a827b54f20d52bcfda4fe7a16a0b) 的示例:

using (var fileStream = new FileStream(uploadfile, FileMode.Open))
    {
        Console.WriteLine("Uploading {0} ({1:N0} bytes)", uploadfile, fileStream.Length);
        client.BufferSize = 4 * 1024; // bypass Payload error large files
        client.UploadFile(fileStream, Path.GetFileName(uploadfile));
    }

请注意,我们打开 FileStream 来读取文件,然后将 Stream 引用传递给 SftpClient。我可以在这里使用 System.IO.Pipelines 来减少内存分配吗?我仍然需要为 SftpClient 提供一个 Stream。

【问题讨论】:

  • 您能否再解释一下您希望达到的目标。
  • @Gilad 我用这个例子更新了我的问题。

标签: c# stream pipeline


【解决方案1】:

现在这似乎是一种利用 PipeReader 的 AsStream() 扩展的方法:

using (var fileStream = new FileStream(uploadfile, FileMode.Open))
    {
        Console.WriteLine("Uploading {0} ({1:N0} bytes)", uploadfile, fileStream.Length);
        client.BufferSize = 4 * 1024; // bypass Payload error large files
        var pipeReader = PipeReader.Create(fileStream);
        client.UploadFile(pipeReader.AsStream(), Path.GetFileName(uploadfile));
    }

【讨论】:

    【解决方案2】:

    免责声明:我不是专家,只是拼凑起来......


    答案(截至 2019 年 1 月)似乎是:对此没有官方支持。

    System.IO.Pipelines 主要是为 networking use cases 创建的。其实2.1发布的管道代码有no support for any endpoints

    这里我们需要一点警告和免责声明:.NET Core 2.1 中发布的管道不包含任何端点实现。

    有一个用于通用流适配器的proposed design for an API,但这是 .NET Core 3.0 里程碑的一部分。

    甚至有 seems to be some reticence 来实现基于文件的管道访问(又名 FileStream 管道等效项)。这尤其令人失望,因为我也希望管道驱动的文件 I/O。

    我认为您目前最好的选择是使用UsePipe() 中的https://github.com/AArnott/Nerdbank.Streams 方法


    更新:这是我刚刚找到的另一个示例https://github.com/tulis/system-io-pipelines-demo/tree/master/src/SystemIoPipelinesDemo/SystemIoPipelinesDemo


    更新:我尝试制作基于管道的文件阅读器。你可以在这里阅读所有相关信息:https://github.com/atruskie/Pipelines.File.Unofficial

    基本上,从性能的角度来看,使用像 Nerdbank.Streams 这样的管道流适配器是一个不错的方法!

    【讨论】:

    • 非常感谢您的澄清。令人失望的是不支持文件流,但至少我现在明白为什么我无法找到任何如何使用管道的示例。
    • @Anthony Truskinger 我想知道为什么在你的基准测试中同步 I/O 比异步 I/O 快得多,我想我发现了原因:你的文件流没有用 FileOptions.Asynchronous 打开.见github.com/atruskie/Pipelines.File.Unofficial/issues/1
    • 我已经更新了基准测试以测试有无FileOptions.Asynchronous
    • 我已经有一段时间没有做这方面的工作了,但是从我从上面的 GitHub 链接 (github.com/dotnet/corefx/issues/27246) 中读到的内容看来,.NET Core 3.0 中应该存在一些适配器跨度>
    猜你喜欢
    • 1970-01-01
    • 2014-05-08
    • 1970-01-01
    • 1970-01-01
    • 2014-06-15
    • 2019-12-14
    • 1970-01-01
    • 2018-11-20
    相关资源
    最近更新 更多