Est-ce que Garbage Collector détruit les objets temporairement non référencés lors d'appels asynchrones dans .NET?

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

Question

Imaginez que je passe un appel asynchrone dans .NET, c’est-à-dire HttpWebRequest.BeginGetResponse, et que l’objet HttpWebRequest n’est pas référencé dans un champ plus large. Est-ce que le ramasse-miettes va le détruire et causer des problèmes?

Exemple de code:

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

Version alternative (avec la requête transmise en tant qu'état asynchrone):

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..
    }
}
Était-ce utile?

La solution

Un objet est considéré comme étant en vie et non admissible à la récupération de place si un thread en direct contient une référence, ou s'il est référencé de manière statique (directement ou indirectement dans les deux cas).

Dans les deux exemples, l'API asynchrone conserve une référence à votre demande (dans le pool de threads où les opérations d'E / S asynchrones sont stockées) et ne sera donc pas collectée jusqu'à la fin.

Autres conseils

Non, le ramasse-miettes ne vous causera pas de problèmes.

Ne supposez pas que, parce que vous n'avez pas accès à l'objet, le ramasse-miettes va le nettoyer.

Le ramasse-miettes commence par un certain nombre de "racines". - objets et références connus accessibles. Ensuite, tous les objets accessibles à partir de ces racines sont trouvés et tout le reste est collecté.

Chaque thread en cours d'exécution, y compris le ou les threads traitant les appels asynchrones, est inclus dans la liste des racines.

Si un objet ne contient aucune référence en ce qui concerne le CPG, vous ne pouvez plus y obtenir une référence. Donc, vous ne pouvez pas avoir un objet qui temporairement n'y ait pas de référence.

(Cela ne suppose rien de sournois comme des jeux de code non gérés ou dangereux)

L'objet reste parfaitement référencé, grâce à la mise en œuvre d'appels asynchrones, qui doivent conserver une liste de toutes les demandes en cours, afin de corréler les données entrantes aux demandes. Très probablement, .NET utilise une variable globale (ou classe) pour stocker les demandes.

Dans le premier exemple de code, pourquoi créez-vous une demande si vous ne l'utilisez pas?

Quoi qu'il en soit, s'il n'existe aucune référence (directe ou indirecte) à un objet provenant de l'un des objets actuellement dans le champ d'application, le GC peut le collecter.

Ainsi, dans votre premier exemple, lorsque le programme quitte la méthode Main, Request est toujours dans la portée (dans un autre thread), de sorte qu'il ne sera pas collecté avant la fin de l'appel asynchrone. Dans votre deuxième exemple, le thread de pool de threads et votre code conservent une référence à votre objet, il ne sera donc évidemment pas collecté.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top