C#中System.IO.Pipelines庫的使用詳解
寫在前面
在進一步了解Socket粘包分包的過程中,了解到了.NET 中的 System.IO.Pipelines,可以更優(yōu)雅高效的解決這個問題;先跟隨官方的示例做個初步的認識。
System.IO.Pipelines 是一個庫,旨在使在 .NET 中執(zhí)行高性能 I/O 更加容易。 該庫的目標為適用于所有 .NET 實現的 .NET Standard。
System.IO.Pipelines 具有高性能的流數據分析功能,可以減少代碼復雜性。
老規(guī)矩通過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結尾,作為數據塊的區(qū)分,利用這個特性定義數據報文的尾部,實現分包。
到此這篇關于C#中System.IO.Pipelines庫的使用詳解的文章就介紹到這了,更多相關C# System.IO.Pipelines內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C#使用OpenCvSharp4庫讀取電腦攝像頭數據并實時顯示
OpenCvSharp4庫是一個基于.Net封裝的OpenCV庫,本文主要給大家介紹了C#使用OpenCvSharp4庫讀取電腦攝像頭數據并實時顯示的詳細方法,感興趣的朋友可以參考下2024-01-01C# Lambda表達式select()和where()的區(qū)別及用法
這篇文章主要介紹了C# Lambda表達式select()和where()的區(qū)別及用法,select在linq中一般會用來提取最后篩選的元素集合,在lambda表達式中通常用where得到元素集合,需要的朋友可以參考下2023-07-07C# WinForm 登錄界面的圖片驗證碼(區(qū)分大小寫+不區(qū)分大小寫)
這篇文章主要介紹了C# WinForm 登錄界面的圖片驗證碼(區(qū)分大小寫+不區(qū)分大小寫),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-02-02c#中Winform實現多線程異步更新UI(進度及狀態(tài)信息)
本篇文章主要介紹了c#中Winform實現多線程異步更新UI(進度及狀態(tài)信息) ,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02如何在C#中使用 CancellationToken 處理異步任務
這篇文章主要介紹了如何在C#中使用 CancellationToken 處理異步任務,幫助大家更好的理解和學習使用c#,感興趣的朋友可以了解下2021-03-03