HttpResponseMessage 的处理是调用请求流的处理

vit*_*itm 3 c# httpclient .net-core httpresponsemessage

我有一个方法,它采用 Stream 参数并将其传递给服务器

public async Task<string> Execute(Stream archive)
    {
        archive.Seek(0, SeekOrigin.Begin);
        using var content = new MultipartFormDataContent();
        content.Add(new StreamContent(archive), "file1", "file1");
        var result = "";
        using (var response = await _client.PostAsync(_uri, content))
        {
            if (response.IsSuccessStatusCode)
            {
                var stringResult = await response.Content.ReadAsStringAsync();
                result = stringResult;
            }
        }
        // here archive is already disposed
        return result;
    }
Run Code Online (Sandbox Code Playgroud)

现在我实现这个方法的重试策略。如果调用此方法的外部代码得到“”结果,则它会尝试再次调用此方法。但档案是在那一刻处理的。我看到存档流在处理响应后立即被处理。为什么?如果在这个方法之后需要外部流参数怎么办?

JHB*_*ius 5

它将StreamContent处理,如其来源Stream中所述。这将由. 这将在 PostAsync 中处理......整个链。MultipartContent

解决方案是对 Stream 进行子类化并删除 dispose 方法,如此处建议的那样。但您必须确保自己处理原始流!编辑:更新。Stream是一个抽象类,所以如果你知道具体的流类型会更容易,例如

public sealed class NoDisposeMemoryStream : MemoryStream
{
    protected override void Dispose(bool disposing) { }
}
Run Code Online (Sandbox Code Playgroud)

否则,您将需要编写自己的完整Stream包装器,请参见底部。

另一种解决方案是在最里面的using块中实现重试机制,archive每次失败时重置查找原点。这可能更安全。


    public sealed class NoDisposeStream : Stream
    {
        private Stream _original;
        public NoDisposeStream(Stream original) => _original = original
            ?? throw new ArgumentNullException(nameof(original));
        public override bool CanRead => _original.CanRead;
        public override bool CanSeek => _original.CanSeek;
        public override bool CanWrite => _original.CanWrite;
        public override long Length => _original.Length;
        public override long Position { get => _original.Position; set { _original.Position = value; } }
        public override void Flush() => _original.Flush();
        public override int Read(byte[] buffer, int offset, int count) => _original.Read(buffer, offset, count);
        public override long Seek(long offset, SeekOrigin origin) => _original.Seek(offset, origin);
        public override void SetLength(long value) => _original.SetLength(value);
        public override void Write(byte[] buffer, int offset, int count) => _original.Write(buffer, offset, count);
        protected override void Dispose(bool disposing) { }
    }
Run Code Online (Sandbox Code Playgroud)