簡體   English   中英

我們應該總是使用 PipeWriter.GetMemory > Advance > Flush 嗎? 我們什么時候使用 WriteAsync?

[英]Should we always use PipeWriter.GetMemory > Advance > Flush? When do we use WriteAsync?

當我遇到以下問題時,我試圖尋找這個問題的答案。

為什么在前 16 個有效字節之后讀取值為 0 的 16 個字節? 是因為我們不應該使用 WriteAsync 嗎?

示例代碼:

var r = new Random();
Pipe testPipe = new Pipe();

var Buffer1 = new byte[16];
r.NextBytes(Buffer1);
await testPipe.Writer.WriteAsync(Buffer1);
testPipe.Writer.Advance(16);
await testPipe.Writer.FlushAsync();

var Buffer2 = new byte[16];
r.NextBytes(Buffer2);
await testPipe.Writer.WriteAsync(Buffer2);
testPipe.Writer.Advance(16);
await testPipe.Writer.FlushAsync();

var result = await testPipe.Reader.ReadAsync();
var Buffer3 = new byte[result.Buffer.Length];
result.Buffer.CopyTo(Buffer3.AsSpan());

沒有全面涵蓋我需要的關於這兩種方法的所有信息,而且我還有一個我不理解的問題。

精簡版

不要在WriteAsync之后調用Advance ,這已經在內部調用,它只應該與 GetMemory 模式一起使用。 另外,不要調用 FlushAsync,這也已經在內部調用了。

var r = new Random();
Pipe testPipe = new Pipe();

var Buffer1 = new byte[16];
r.NextBytes(Buffer1);
await testPipe.Writer.WriteAsync(Buffer1);
//testPipe.Writer.Advance(16);
//await testPipe.Writer.FlushAsync();

var Buffer2 = new byte[16];
r.NextBytes(Buffer2);
await testPipe.Writer.WriteAsync(Buffer2);
//testPipe.Writer.Advance(16);
//await testPipe.Writer.FlushAsync();

var result = await testPipe.Reader.ReadAsync();
var Buffer3 = new byte[result.Buffer.Length];
result.Buffer.CopyTo(Buffer3.AsSpan());

長版

WriteAsync已經在內部調用Advance

在源碼中, WriteAsync定義在https://github.com/dotnet/runtime/blob/master/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.DefaultPipeWriter.cs中。 即 function 只需調用 pipe 上的內部 function return _pipe.WriteAsync(source, cancellationToken); ,在https://github.com/dotnet/runtime/blob/master/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/Pipe.cs中定義。 function 調用AdvanceCore ,它是Advance的底層實現。

它還在內部調用Flush ,因此在WriteAsync之后不需要它。 Flush操作是唯一的異步操作。

WriteAsync的文檔當前未提及此行為 - 請參閱https://docs.microsoft.com/en-us/dotnet/api/system.io.pipelines.pipewriter.writeasync?view=dotnet-plat-ext-3.1

作者稱使用WriteAsync不好 - 請參閱https://mgravell.github.io/pipelines.docs/Writing/ 這是因為 PipeWriter 在內部有效地使用了“GetMemory > Advance > Flush”方法。 這意味着您養成了創建 Memory 緩沖區然后將其復制到 pipe memory 的習慣,這是低效的。 (作者沒有提到還有API仍然不寫Memory,只會寫byte[])

當您擁有自己的 byte[] 幀時,使用WriteAsync可能更有效,因為編碼似乎通過可用的 memory 塊順序迭代和重用。 這可以防止在池中不必要地創建新的 Memory 塊。 池的存在是為了最大限度地減少對象的創建和 GC,擔心 GC 開銷(以及 memory 頁面緩存成功?)超過幾個 CPU 周期。

如果您正在使用支持Memory<byte>的函數,請使用PipeWriter.GetMemory獲取正確大小的 Memory 塊,然后您可以直接寫入緩沖區,該緩沖區將通過 pipe 轉發到閱讀器端。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM