我正在嘗試按照Microsoft 的建議將使用 .Net 6 的 ASP.NET 應用程式從 Stream 切換到 PipeReader 。這是我的自定義方法:
private static async Task<byte[]> GetRequestBodyBytesAsync(PipeReader reader)
{
byte[] bodyBytes;
do
{
ReadResult readResult = await reader.ReadAsync();
if (readResult.IsCompleted || readResult.IsCanceled)
{
ReadOnlySequence<byte> slice = readResult.Buffer.Slice(readResult.Buffer.Start, readResult.Buffer.End);
bodyBytes = BuffersExtensions.ToArray(slice);
reader.AdvanceTo(readResult.Buffer.End);
break;
}
} while (true);
return bodyBytes;
}
但是,當我在控制器中使用上述靜態方法時:
[HttpPost]
[Route(MyUrl)]
public async Task MyPostAsync()
{
byte[] bodyBytes = await GetRequestBodyBytesAsync(Request.BodyReader);
MyProtobuf myProtobuf = MyProtobuf.Parser.ParseFrom(bodyBytes);
然后我可以在除錯器中看到readResult.IsCompleted永遠不會是真的并且readResult.Buffer保持相同的 21 個位元組。
添加else { reader.AdvanceTo(readResult.Buffer.Start); }并沒有改變任何東西。
我需要完整的位元組陣列,這樣我就可以將它傳遞給 Protobuf 決議方法(protobuf 沒有流式決議器)......我怎樣才能在這里使用 IO.Pipelines?
更新:
以下方法(在PipeReaderExtensions.cs中找到并由 Marc 確認)現在適用于我,甚至可以通過避免復制資料來進一步改進 - 請參閱下面 Marc 的精彩評論。
private static async Task<byte[]> GetRequestBodyBytesAsync(PipeReader reader)
{
do
{
ReadResult readResult = await reader.ReadAsync();
if (readResult.IsCompleted || readResult.IsCanceled)
{
return readResult.Buffer.ToArray();
}
// consume nothing, keep reading from the pipe reader until all data is there
reader.AdvanceTo(readResult.Buffer.Start, readResult.Buffer.End);
} while (true);
}
uj5u.com熱心網友回復:
AdvanceTo你應該在 every 之后呼叫ReadAsync,所以你真的應該有一個類似的else東西:
reader.AdvanceTo(readResult.Buffer.Start, readResult.Buffer.End);
這表示“我已經檢查了所有內容,并且沒有消耗任何內容”(至少在語意上;您沒有真正看過任何內容并不重要 - 關鍵是要說“所有這些位元組:對我沒有用然而”) - 這意味著ReadAsync 現在不應該嘗試給你任何其他東西,直到它有一些額外的資料或資料已經結束。實際上,我有點驚訝它并沒有拋出例外。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/490448.html
