亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C#中的高效IO庫(kù)System.IO.Pipelines

 更新時(shí)間:2022年07月02日 09:33:03   作者:天方  
這篇文章介紹了C#中的高效IO庫(kù)System.IO.Pipelines,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

我們?cè)诰帉?xiě)網(wǎng)絡(luò)程序的時(shí)候,經(jīng)常會(huì)進(jìn)行如下操作:

  • 申請(qǐng)一個(gè)緩沖區(qū)

  • 從數(shù)據(jù)源中讀入數(shù)據(jù)至緩沖區(qū)

  • 解析緩沖區(qū)的數(shù)據(jù)

  • 重復(fù)第2步

表面上看來(lái)這是一個(gè)很常規(guī)而簡(jiǎn)單的操作,但實(shí)際使用過(guò)程中往往存在如下痛點(diǎn):

數(shù)據(jù)讀不全:

可能不能在一次read操作中讀入所有需要的數(shù)據(jù),因此需要在緩沖區(qū)中維護(hù)一個(gè)游標(biāo),記錄下次讀取操作的起始位置,這個(gè)游標(biāo)帶了了不小的復(fù)雜度:

  • 從緩沖區(qū)讀數(shù)據(jù)時(shí),要根據(jù)游標(biāo)計(jì)算緩沖區(qū)起始寫(xiě)位置,以及剩余空間大小。增加了讀數(shù)據(jù)的復(fù)雜度。

  • 解析數(shù)據(jù)也是復(fù)用這個(gè)緩沖區(qū)的,解析的時(shí)候也要判斷游標(biāo)起始位置,剩余空間大小。同時(shí)增加了解析數(shù)據(jù)的復(fù)雜度。

  • 解析玩了后還要移動(dòng)游標(biāo),重新標(biāo)記緩沖區(qū)起始位置,再次增加了復(fù)雜度。

緩沖區(qū)容量有限:

由于緩沖區(qū)有限,可能申請(qǐng)的緩沖區(qū)不夠用,需要引入動(dòng)態(tài)緩沖區(qū)。這也大幅加大了代碼的復(fù)雜度。

  • 如果每次都申請(qǐng)更大的內(nèi)存,一方面帶來(lái)的內(nèi)存申請(qǐng)釋放開(kāi)銷(xiāo),另一方面需要將原來(lái)的數(shù)據(jù)移動(dòng),并更新游標(biāo),帶來(lái)更復(fù)雜的邏輯。

  • 如果靠多段的內(nèi)存組成一個(gè)邏輯整理,數(shù)據(jù)的讀寫(xiě)方式都比較復(fù)雜。

  • 使用完后的內(nèi)存要釋放,如果需要更高的效率還要維持一個(gè)內(nèi)存池。

讀和用沒(méi)有分離

我們的業(yè)務(wù)本身只關(guān)心使用操作,但讀和用操作沒(méi)有分離,復(fù)雜的都操作導(dǎo)致用操作也變得復(fù)雜,并且嚴(yán)重干擾業(yè)務(wù)邏輯。

今天介紹微軟新推出的一個(gè)庫(kù):System.IO.Pipelines(需要在Nuget上安裝),用于解決這些痛點(diǎn)。它主要包含一個(gè)Pipe對(duì)象,它有一個(gè)Writer屬性和Reader屬性。

var pipe   = new Pipe();
var writer = pipe.Writer;
var reader = pipe.Reader;

Writer對(duì)象

Writer對(duì)象用于從數(shù)據(jù)源讀取數(shù)據(jù),將數(shù)據(jù)寫(xiě)入管道中;它對(duì)應(yīng)業(yè)務(wù)中的"讀"操作。

var?content?=?Encoding.Default.GetBytes("hello?world");
var?data????=?new?Memory<byte>(content);
var?result??=?await?writer.WriteAsync(data);

另外,它也有一種使用Pipe申請(qǐng)Memory的方式

var?buffer?=?writer.GetMemory(512);
content.CopyTo(buffer);
writer.Advance(content.Length);
var?result?=?await?writer.FlushAsync();

Reader對(duì)象

Reader對(duì)象用于從管道中獲取數(shù)據(jù)源,它對(duì)應(yīng)業(yè)務(wù)中的"用"操作。

首先獲取管道的緩沖區(qū):

var?result?=?await?reader.ReadAsync();
var?buffer?=?result.Buffer;

這個(gè)Buffer是一個(gè)ReadOnlySequence<byte>對(duì)象,它是一個(gè)相當(dāng)好的動(dòng)態(tài)內(nèi)存對(duì)象,并且相當(dāng)高效。它本身由多段Memory<byte>組成,查看Memory段的方法有:

  • IsSingleSegment: 判斷是否只有一段Memory<byte>

  • First: 獲取第一段Memory<byte>

  • GetEnumerator: 獲取分段的Memory<byte>

它從邏輯上也可以看成一段連續(xù)的Memory<byte>,也有類(lèi)似的方法:

  • Length: 整個(gè)數(shù)據(jù)緩沖區(qū)長(zhǎng)度

  • Slice: 分割緩沖區(qū)

  • CopyTo: 將內(nèi)容復(fù)制到Span中

  • ToArray: 將內(nèi)容復(fù)制到byte[]中

另外,它還有一個(gè)類(lèi)似游標(biāo)的位置對(duì)象SequencePosition,可以從其Position相關(guān)函數(shù)中使用,這里就不多介紹了。

這個(gè)緩沖區(qū)解決了"數(shù)據(jù)讀不夠"的問(wèn)題,一次讀取的不夠下次可以接著讀,不用緩沖區(qū)的動(dòng)態(tài)分配,高效的內(nèi)存管理方式帶來(lái)了良好的性能,好用的接口是我們能更關(guān)注業(yè)務(wù)。

獲取到緩沖區(qū)后,就是使用緩沖區(qū)的數(shù)據(jù)

var?data?=?buffer.ToArray();

使用完后,告訴PIPE當(dāng)前使用了多少數(shù)據(jù),下次接著從結(jié)束位置后讀起

reader.AdvanceTo(buffer.GetPosition(4));

這是一個(gè)相當(dāng)實(shí)用的設(shè)計(jì),它解決了"讀了就得用"的問(wèn)題,不僅可以將不用的數(shù)據(jù)下次再使用,還可以實(shí)現(xiàn)Peek的操作,只讀但不改變游標(biāo)。

交互

除了"讀"和"用"操作外,它們之間還需要一些交互,例如:

  • 讀過(guò)程中數(shù)據(jù)源不可用,需要停止使用

  • 使用過(guò)程中業(yè)務(wù)結(jié)束,需要中止數(shù)據(jù)源。

Reader和Writer都有一個(gè)Complete函數(shù),用于通知結(jié)束:

reader.Complete();
writer.Complete();

在Writer寫(xiě)入和Reader讀取時(shí),會(huì)獲得一個(gè)結(jié)果

FlushResult?result?=?await?writer.FlushAsync();
ReadResult?result?=?await?reader.ReadAsync();

它們都有一個(gè)IsComplete屬性,可以根據(jù)它是否為true判斷是否已經(jīng)結(jié)束了讀和寫(xiě)的操作。

取消

在寫(xiě)入和讀取的時(shí)候,也可以傳入一個(gè)CancellationToken,用于取消相應(yīng)的操作。

writer.FlushAsync(CancellationToken.None);
reader.ReadAsync(CancellationToken.None);

如果取消成功,對(duì)應(yīng)的Result的IsCanceled則為true(沒(méi)有驗(yàn)證過(guò))

到此這篇關(guān)于C#高效IO庫(kù)System.IO.Pipelines的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#實(shí)現(xiàn)Zip壓縮目錄中所有文件的方法

    C#實(shí)現(xiàn)Zip壓縮目錄中所有文件的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)Zip壓縮目錄中所有文件的方法,涉及C#針對(duì)文件的讀寫(xiě)與zip壓縮相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • C#多線(xiàn)程處理多個(gè)隊(duì)列數(shù)據(jù)的方法

    C#多線(xiàn)程處理多個(gè)隊(duì)列數(shù)據(jù)的方法

    這篇文章主要介紹了C#多線(xiàn)程處理多個(gè)隊(duì)列數(shù)據(jù)的方法,涉及C#線(xiàn)程與隊(duì)列的相關(guān)操作技巧,需要的朋友可以參考下
    2015-07-07
  • C#縮略圖多路徑多格式保存的實(shí)例

    C#縮略圖多路徑多格式保存的實(shí)例

    這篇文章介紹了C#縮略圖多路徑多格式保存的實(shí)例,有需要的朋友可以參考一下
    2013-07-07
  • c#語(yǔ)言程序構(gòu)建基塊

    c#語(yǔ)言程序構(gòu)建基塊

    這篇文章主要介紹了c#語(yǔ)言程序構(gòu)建基塊,關(guān)于c#程序構(gòu)建基塊我們要從成員開(kāi)始,class?的成員要么是靜態(tài)成員,要么是實(shí)例成員。?靜態(tài)成員屬于類(lèi),而實(shí)例成員則屬于對(duì)象,具體內(nèi)容需要的小伙伴可以參考下面文章的詳細(xì)內(nèi)容
    2021-12-12
  • C#中事件的定義和使用

    C#中事件的定義和使用

    在使用事件時(shí),通常要定義兩個(gè)方法,一個(gè)是和事件定義的委托簽名一致的方法。下面讓我們看看使用事件的具體步驟。
    2016-06-06
  • C#操作txt文件,進(jìn)行清空添加操作的小例子

    C#操作txt文件,進(jìn)行清空添加操作的小例子

    這篇文章介紹了C#操作txt文件,進(jìn)行清空添加操作的小例子,有需要的朋友可以參考一下
    2013-09-09
  • 解析C#網(wǎng)絡(luò)編程中的Http請(qǐng)求

    解析C#網(wǎng)絡(luò)編程中的Http請(qǐng)求

    這篇文章主要介紹了C#網(wǎng)絡(luò)編程中的Http請(qǐng)求,不過(guò)這次也使我對(duì)C#網(wǎng)絡(luò)編程了解的更多,算是一次學(xué)習(xí)經(jīng)歷吧,文章結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-03-03
  • LZW壓縮算法 C#源碼

    LZW壓縮算法 C#源碼

    本文分享了一個(gè)LZW壓縮算法的C#源碼,有需要的朋友可以參考一下。
    2016-06-06
  • 如何保存Unity中的Log日志

    如何保存Unity中的Log日志

    這篇文章主要介紹了如何保存Unity中的Log日志的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • 詳解C#中普通緩存的使用

    詳解C#中普通緩存的使用

    緩存的概念及優(yōu)缺點(diǎn)在這里就不多做介紹,當(dāng)然緩存包含多種有普通緩存、客戶(hù)端緩存、DNS緩存、反向代理緩存以及分布式緩存等等。今天主要聊一聊C#通過(guò)編碼來(lái)實(shí)現(xiàn)普通的緩存、話(huà)不多說(shuō)直接上代碼。
    2021-05-05

最新評(píng)論