![](/img/trans.png)
[英]Should we always use .Find() rather than .FirstOrDefault() when we have the primary key in Entity Framework Core?
[英]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.