Следует ли избавляться от ссылки WebResponse в WebException, если она поднята из WebClient?

Связанный вопрос: WebClient в .Net не освобождает ресурсы сокета

При отладке проблемы с утечкой ресурсов я заметил, что System.Net.WebException (одноразовый тип) содержит ссылку на System.Net.WebResponse (одноразовый тип). Мне интересно, следует ли мне избавляться от этой ссылки при явной обработке WebResponse, как в следующем фрагменте.

using (WebClient client = new WebClient())
{
    WebException ex = Assert.Throws<WebException>(() => client.OpenRead(myUri));
    Assert.That(
        ((HttpWebResponse)ex.Response).StatusCode,
        Is.EqualTo(HttpStatusCode.ServiceUnavailable));
}

Ссылка WebException.WebResponse является копией существующей ссылки в WebClient. Я думал, что он будет удален через WebClient.Dispose, но это не так, поскольку WebClient не отменяет защищенный базовый метод Component.Dispose(bool). Фактически, дизассемблирование предполагает, что ресурс WebResponse никогда не удаляется, а вместо этого устанавливается значение null, когда он больше не нужен.

public Stream OpenRead(Uri address)
{
    Stream stream2;

    // --- removed for brevity ---

    WebRequest request = null;
    this.ClearWebClientState();
    try
    {
        request = this.m_WebRequest = this.GetWebRequest(this.GetUri(address));
        Stream responseStream = (this.m_WebResponse = this.GetWebResponse(request)).GetResponseStream();

        // --- removed for brevity ---

        stream2 = responseStream;
    }
    catch (Exception exception)
    {

        // --- removed for brevity ---

        AbortRequest(request);
        throw exception;
    }
    finally
    {
        this.CompleteWebClientState();
    }
    return stream2;
}

... с ClearWebClientState() следующим образом:

private void ClearWebClientState()
{
    // --- removed for brevity ---

    this.m_WebResponse = null;
    this.m_WebRequest = null;
}

person Steve Guidi    schedule 30.03.2011    source источник


Ответы (1)


Чтобы убедиться, что ресурсы WebResponse освобождены, вы можете явно вызвать метод Close.

Вот модифицированный метод ClearWebClientState:

private void ClearWebClientState()
{
    // --- removed for brevity ---
    if ( this.m_WebResponse != null )
        this.m_WebResponse.Close();
    this.m_WebResponse = null;

    this.m_WebRequest = null;
}
person Vadym Stetsiak    schedule 12.06.2011
comment
Благодарю за ваш ответ. Я понимаю, что Close() освободит ресурс, однако приведенный мной пример взят из декомпилированной реализации типа System.Web.WebClient, и у меня нет возможности изменить это :) - person Steve Guidi; 15.06.2011