Уничтожает ли сборщик мусора временно не связанные объекты во время асинхронных вызовов в .NET? - PullRequest
9 голосов
/ 07 января 2009

Представьте, что я сделаю асинхронный вызов в .NET, то есть HttpWebRequest.BeginGetResponse, а на объект HttpWebRequest нет ссылки в более широкой области. Будет ли сборщик мусора уничтожать его и вызывать проблемы?

Пример кода:

using System;
using System.Net;

public class AsyncHttpWebRequest
{
    void Main()
    {
        var Request = HttpWebRequest.Create("http://www.contoso.com");
        var result = Request.BeginGetResponse(GetResponseCallback, null);
    }

    private void GetResponseCallback(IAsyncResult AsyncResult)
    {
        // Do Something..
    }
}

Альтернативная версия (с запросом, передаваемым как AsyncState):

using System;
using System.Net;

public class AsyncHttpWebRequest
{
    void Main()
    {
        var Request = HttpWebRequest.Create("http://www.contoso.com");
        var result = Request.BeginGetResponse(GetResponseCallback, Request);
    }

    private void GetResponseCallback(IAsyncResult AsyncResult)
    {
        // Do Something..
    }
}

Ответы [ 5 ]

11 голосов
/ 07 января 2009

Объект считается живым и непригодным для сбора мусора, если какой-либо живой поток содержит ссылку на него или если на него ссылаются статически (прямо или косвенно в обоих случаях).

В обоих примерах асинхронный API хранит ссылку на ваш запрос (в пуле потоков, в котором выполняются асинхронные операции ввода-вывода), поэтому он не будет собирать мусор до тех пор, пока не завершится.

3 голосов
/ 07 января 2009

Нет, сборщик мусора не доставит вам проблем.

Не думайте, что, поскольку у вас нет доступа к объекту, сборщик мусора собирается его очистить.

Сборщик мусора начинается с ряда «корней» - объектов и ссылок, которые, как известно, достижимы. Затем все объекты, достижимые из этих корней, найдены, а все остальное собрано.

Каждый работающий поток, включая потоки, обрабатывающие асинхронные вызовы, включен в список корней.

1 голос
/ 07 января 2009

Если объект не имеет ссылок в том, что касается ГХ, вы больше не можете получить ссылку на него. Таким образом, вы не можете иметь объект, который временно не имеет ссылки на него.

(Это не предполагает ничего хитрого, как неуправляемый или небезопасный код, играющий в игры)

0 голосов
/ 07 января 2009

На объект по-прежнему ссылаются очень хорошо, благодаря реализации асинхронных вызовов - который должен поддерживать список всех открытых запросов, чтобы соотнести входящие данные с запросами. Скорее всего, .NET использует глобальную (или классовую) переменную для хранения запросов.

0 голосов
/ 07 января 2009

В первом примере кода, почему вы создаете Запрос, если вы его не используете?

В любом случае, если не существует ссылки (прямой или косвенной) на объект из какого-либо из объектов, находящихся в настоящее время в области видимости, GC может собрать его.

Итак, в вашем первом примере, когда программа завершает работу, метод Main все еще находится в области видимости (в другом потоке), поэтому он не будет собран до завершения асинхронного вызова. Во втором примере и поток пула потоков, и ваш код сохраняют ссылку на ваш объект, поэтому, очевидно, он также не будет собран.

...