Уничтожает ли сборщик мусора временно не связанные объекты во время асинхронных вызовов в .NET?

StackOverflow https://stackoverflow.com/questions/421547

Вопрос

Представьте, что я сделаю асинхронный вызов в .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..
    }
}
Это было полезно?

Решение

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top