C#中System.IO.Pipelines库的使用详解

 更新时间:2023年12月26日 08:23:50   作者:rjcql  
System.IO.Pipelines 是一个库,旨在使在 .NET 中执行高性能 I/O 更加容易,本文主要为大家详细介绍了System.IO.Pipelines具体使用方法,感兴趣的可以了解下

写在前面

在进一步了解Socket粘包分包的过程中,了解到了.NET 中的 System.IO.Pipelines,可以更优雅高效的解决这个问题;先跟随官方的示例做个初步的认识。

System.IO.Pipelines 是一个库,旨在使在 .NET 中执行高性能 I/O 更加容易。 该库的目标为适用于所有 .NET 实现的 .NET Standard。
System.IO.Pipelines 具有高性能的流数据分析功能,可以减少代码复杂性。

老规矩通过NuGet安装该类库

代码实现

using System.Buffers;
using System.IO.Pipelines;
using System.Text;
 
class Program
{
    static async Task Main()
    {
        using var stream = File.OpenRead("lorem-ipsum.txt");
 
        var reader = PipeReader.Create(stream);
        var writer = PipeWriter.Create(
            Console.OpenStandardOutput(),
            new StreamPipeWriterOptions(leaveOpen: true));
 
        WriteUserCancellationPrompt();
 
        var processMessagesTask = ProcessMessagesAsync(reader, writer);
        var userCanceled = false;
        var cancelProcessingTask = Task.Run(() =>
        {
            while (char.ToUpperInvariant(Console.ReadKey().KeyChar) != 'C')
            {
                WriteUserCancellationPrompt();
            }
 
            userCanceled = true;
 
            // No exceptions thrown
            reader.CancelPendingRead();
            writer.CancelPendingFlush();
        });
 
        await Task.WhenAny(cancelProcessingTask, processMessagesTask);
 
        Console.WriteLine(
            $"\n\nProcessing {(userCanceled ? "cancelled" : "completed")}.\n");
    }
 
    static void WriteUserCancellationPrompt() =>
        Console.WriteLine("Press 'C' to cancel processing...\n");
 
    static async Task ProcessMessagesAsync(
        PipeReader reader,
        PipeWriter writer)
    {
        try
        {
            while (true)
            {
                ReadResult readResult = await reader.ReadAsync();
                ReadOnlySequence<byte> buffer = readResult.Buffer;
 
                try
                {
                    if (readResult.IsCanceled)
                    {
                        break;
                    }
 
                    if (TryParseLines(ref buffer, out string message))
                    {
                        FlushResult flushResult =
                            await WriteMessagesAsync(writer, message);
 
                        if (flushResult.IsCanceled || flushResult.IsCompleted)
                        {
                            break;
                        }
                    }
 
                    if (readResult.IsCompleted)
                    {
                        if (!buffer.IsEmpty)
                        {
                            throw new InvalidDataException("Incomplete message.");
                        }
                        break;
                    }
                }
                finally
                {
                    reader.AdvanceTo(buffer.Start, buffer.End);
                }
            }
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex);
        }
        finally
        {
            await reader.CompleteAsync();
            await writer.CompleteAsync();
        }
    }
 
    static bool TryParseLines(
        ref ReadOnlySequence<byte> buffer,
        out string message)
    {
        SequencePosition? position;
        StringBuilder outputMessage = new();
 
        while (true)
        {
            position = buffer.PositionOf((byte)'\n');
 
            if (!position.HasValue)
                break;
 
            outputMessage.Append(Encoding.ASCII.GetString(buffer.Slice(buffer.Start, position.Value)))
                        .AppendLine();
 
            buffer = buffer.Slice(buffer.GetPosition(1, position.Value));
        };
 
        message = outputMessage.ToString();
        return message.Length != 0;
    }
 
    static ValueTask<FlushResult> WriteMessagesAsync(
        PipeWriter writer,
        string message) =>
        writer.WriteAsync(Encoding.ASCII.GetBytes(message));
}

调用示例

总结

例子中用到的文本文件是一个以\n 换行符作为结尾的多行文本,微软官方示例没有提供,这个是自己建的测试文件,如果没有检测到\n会抛出异常。

 从运行的结果可以看到,从传入的流中识别以\n结尾,作为数据块的区分,利用这个特性定义数据报文的尾部,实现分包。

到此这篇关于C#中System.IO.Pipelines库的使用详解的文章就介绍到这了,更多相关C# System.IO.Pipelines内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 深入理解C#实现快捷键(系统热键)响应的方法

    深入理解C#实现快捷键(系统热键)响应的方法

    本篇文章是对使用C#实现快捷键(系统热键)响应的方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C#实现批量删除PDF页面(单页/多页)的实战技巧

    C#实现批量删除PDF页面(单页/多页)的实战技巧

    在自动化文档处理流程中,PDF 文件可能因导出错误、内容重复或格式转换问题而包含多余页面,本文演示如何使用免费库 Free Spire.PDF for .NET 删除 PDF 文件中的单个或多个页面,希望对大家有所帮助
    2026-04-04
  • 详解C#如何实现隐式类型转换

    详解C#如何实现隐式类型转换

    Result 类型是许多编程语言中处理错误的常用方式,包括 C# 的 dotNext 库。在本文中,我们将通过例子回顾 C# 中 using 语句和隐式类型转换的使用,感兴趣的可以了解一下
    2023-01-01
  • C#中线程同步对象的方法分析

    C#中线程同步对象的方法分析

    这篇文章主要介绍了C#中线程同步对象的方法,较为详细的分析了线程同步的原理与实现方法,并给出了实例总结,是比较实用的技巧,需要的朋友可以参考下
    2014-12-12
  • C# 中 Array和 ArrayList详解及区别

    C# 中 Array和 ArrayList详解及区别

    这篇文章主要介绍了C# 中 Array和 ArrayList详解及区别的相关资料,需要的朋友可以参考下
    2017-01-01
  • C#基于TimeSpan实现倒计时效果的方法

    C#基于TimeSpan实现倒计时效果的方法

    这篇文章主要介绍了C#基于TimeSpan实现倒计时效果的方法,比较实用的功能,需要的朋友可以参考下
    2014-08-08
  • C# Aspose.Words 删除word中的图片操作

    C# Aspose.Words 删除word中的图片操作

    这篇文章主要介绍了C# Aspose.Words 删除word中的图片操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • c#反射表达式树模糊搜索示例

    c#反射表达式树模糊搜索示例

    这篇文章主要介绍了c#反射表达式树模糊搜索示例,反射实体T,非datetime字段反射获取表达式树,需要的朋友可以参考下
    2014-02-02
  • C# cefSharep控件的使用详情

    C# cefSharep控件的使用详情

    本文主要介绍了C# cefSharep控件的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • C#中DataGridView操作技巧

    C#中DataGridView操作技巧

    这篇文章主要介绍了C#中DataGridView操作技巧,包括了DataGridView的初始化、添加行、添加列、排序等操作技巧,非常具有实用价值,需要的朋友可以参考下
    2014-12-12

最新评论