¿El recolector de basura destruye temporalmente los objetos no referenciados durante las llamadas asíncronas en .NET?

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

Pregunta

Imagine que haré una llamada asíncrona en .NET, es decir, HttpWebRequest.BeginGetResponse, y el objeto HttpWebRequest no está referenciado en un ámbito más amplio. ¿El recolector de basura lo destruirá y causará problemas?

Código de ejemplo:

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

Versión alternativa (con la solicitud aprobada como 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..
    }
}
¿Fue útil?

Solución

Se considera que un objeto está vivo y no es elegible para la recolección de basura si algún hilo en vivo contiene una referencia a él, o si está referenciado estáticamente (directa o indirectamente en ambos casos).

En ambos ejemplos, la API asíncrona mantiene una referencia a su solicitud (dentro del grupo de subprocesos donde se alojan las operaciones asíncronas de E / S) y, por lo tanto, no se recogerá la basura hasta que se complete.

Otros consejos

No, el recolector de basura no le causará problemas.

No asuma que porque usted no tiene acceso al objeto, el recolector de basura lo limpiará.

El recolector de basura comienza con una serie de "raíces" - Objetos y referencias que se conozcan accesibles. Luego, se encuentran todos los objetos accesibles desde esas raíces, y todo lo demás se recoge.

Cada subproceso en ejecución, incluidos los subprocesos que procesan las llamadas asíncronas, se incluyen en la lista de raíces.

Si un objeto no tiene referencias en lo que respecta al GC, ya no puede obtener una referencia a él. Por lo tanto, no puede tener un objeto que temporalmente no tenga una referencia a él.

(Esto no supone nada disimulado como juegos de código no administrados o inseguros)

El objeto permanece referenciado perfectamente, mediante la implementación de llamadas asíncronas, que deben mantener una lista de todas las solicitudes abiertas, para correlacionar los datos entrantes con las solicitudes. Lo más probable es que .NET use una variable global (o de clase) para almacenar las solicitudes.

En el primer código de ejemplo, ¿por qué crea Solicitud, si no la usa?

De todos modos, si no existe una referencia (directa o indirecta) a un objeto de alguno de los objetos actualmente en el ámbito, el GC puede recopilarlo.

Entonces, en su primer ejemplo, cuando el programa sale del método principal, la solicitud aún está dentro del alcance (en otro hilo), por lo que no se recopilará hasta que finalice la llamada asíncrona. En su segundo ejemplo, ambos, el subproceso de grupo de subprocesos y su código mantienen una referencia a su objeto, por lo que, obviamente, no se recopilará también.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top