Следует ли утилизировать ссылку WebResponse в WebException, если она возникла из WebClient? - PullRequest
11 голосов
/ 30 марта 2011

Смежный вопрос: 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 никогда не удаляется, а устанавливается в ноль, когда он больше не нужен.

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;
}

1 Ответ

0 голосов
/ 12 июня 2011

Чтобы быть уверенным, что ресурсы 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;
}
...