我正在尝试使用 .Net 6 将我的 ASP.NET 应用程序从 Stream 切换到 PipeReader按照微软的推荐 https://youtu.be/1koWtKkKb_o。这是我的自定义方法:
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 字节。
Adding else { reader.AdvanceTo(readResult.Buffer.Start); }
没有改变任何东西。
我需要完整的字节数组,以便我可以将其传递给 Protobuf 解析方法(protobuf 没有流解析器)...我如何在这里使用 IO.Pipelines?
UPDATE:
以下方法(见PipeReaderExtensions.cs https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/common/testassets/Tests.Utils/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);
}