【问题标题】:"stream was not readable" ArgumentException when using ReadAsStreamAsync with StreamReader将 ReadAsStreamAsync 与 StreamReader 一起使用时出现“流不可读”ArgumentException
【发布时间】:2015-09-08 14:43:49
【问题描述】:

我有以下代码可以使用 StreamReader 读取和处理 Http get 请求的响应:

try
{
    Stream stream = await ExecuteRequestAsync(uriBuilder.Uri, HttpMethod.Get).ConfigureAwait(false);
    if (stream != null)
    {
        using (StreamReader sr = new StreamReader(stream))
        {
            using (JsonTextReader reader = new JsonTextReader(sr))
            {
                ...
            }
        }
    }
}
catch (Exception ReadingStreamException)
{

}

private async Task<stream> ExecuteRequestAsync(Uri uri, HttpMethod method)
{
    Stream stream;
    using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, uri))
    {
    try
    {
        stopwatch.Start();
        using (HttpResponseMessage responseMessage = await this.httpClient.SendAsync(httpRequestMessage).ConfigureAwait(false))
        {
            stream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false);
        }
    }
    catch(Exception GettingStreamException)
    {
        // Error checking code
    }

    return stream;
}

使用(StreamReader sr = new StreamReader(stream)) 的行向ArgumentException 类型的ReadingStreamException 抛出异常,详细信息为“Stream was not readable”。上面的代码有问题吗?

【问题讨论】:

    标签: c# stream async-await task-parallel-library streamreader


    【解决方案1】:

    发生这种情况是因为当您处置 HttpResponseMessage 时,它会处置底层流。来自the source

    private HttpContent content;
    protected virtual void Dispose(bool disposing)
    {
        if (disposing && !disposed)
        {
            disposed = true;
            if (content != null)
            {
                content.Dispose();
            }
        }
    }
    

    您可以复制流,或者干脆不释放HttpResponseMessage,因为在将底层流传递给StreamReader 时无论如何都会释放它。我会选择后者:

    private async Task<Stream> ExecuteRequestAsync(Uri uri, HttpMethod method)
    {
        Stream stream = null;
        using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage(method, uri))
        {
           try
           {
              stopwatch.Start();
              HttpResponseMessage responseMessage = await httpClient
                                                          .SendAsync(httpRequestMessage)
                                                          .ConfigureAwait(false);
    
              stream = await responseMessage.Content.ReadAsStreamAsync()
                                                    .ConfigureAwait(false);
           }
           catch(Exception GettingStreamException)
           {
              // Error checking code
           }  
        }
        return stream;
    }
    

    【讨论】:

    • 次要建议:有一种极端情况可能不会释放 HttpResponseMessage 中的数据:其中创建了 HttpResponseMessage 对象并在分配 StreamReader 之前引发了异常。因此,我删除了该函数,将代码完全移到了一个地方,以获取 HttpResponseMessage 并使用 StreamReader 读取它。
    猜你喜欢
    • 2014-10-27
    • 1970-01-01
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 2018-12-26
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    相关资源
    最近更新 更多