c# - collector - Passer le paramètre dans un Task.Factory.StartNew



asp.net garbage-collection (3)

Si vous êtes préoccupé par injectedString peut être "garbage collection" avant myClass.Method(injectedString); fonctionne?

La réponse est non . Vous n'avez pas besoin de vous en préoccuper, car injectedString n'est plus une variable locale quand elle est fermée dans le lambda . Il deviendra un champ dans la nouvelle classe générée par le compilateur.

Si vous vous inquiétez, est-ce que le ramasseur de déchets va le ramasser au bon moment? La réponse est oui , elle le fera lorsque l'instance de cette classe sera hors de portée et ne sera pas référencée dans le code managé. Cela arriverait certainement une fois que la Task terminée et sortira de sa portée .

https://src-bin.com

Étant donné le code suivant:

string injectedString = "Read string out of HttpContext";
Task.Factory.StartNew(() =>
 {
    MyClass myClass = new MyClass();
    myClass.Method(injectedString);
 }

Est-ce la meilleure façon de passer la chaîne dans la tâche / thread?

Mes préoccupations avec cette méthode sont:

  • Le garbage collector sait-il quand la chaîne est hors contexte et la nettoie correctement?
  • Existe-t-il un meilleur moyen d'injecter des dépendances dans une tâche en rompant le lien vers l'objet dans le thread principal?

C'est dans un webservice Asp.Net, si c'est important et c'est un thread de type fire and forget, je n'attends aucune réponse.

Ma chaîne va en fait être lue à partir de HttpContext , ce qui est une des raisons pour lesquelles je l'injecte de cette manière (Thread n'a pas accès aux threads appelant HtppContext )


Answer #1

Votre lambda sera hissé dans une classe générée par le compilateur. La variable injectedString deviendra un champ de cette classe.

Ainsi, il sera collecté lorsque la classe générée est hors de portée (ce qui est fondamentalement à la fin de votre lambda), et le GC décide d'effectuer une collecte.

En réponse à votre commentaire:

Il n'y a pas de duplication. Le compilateur tourne ceci:

 string injectedString = "Read string out of HttpContext";
 Task.Factory.StartNew(() =>
 {
    MyClass myClass = new MyClass();
    myClass.Method(injectedString);
 }

Dans ceci:

CompilerGeneratedClass c1 = new CompilerGeneratedClass();
c1.injectedString = "Read string out of HttpContext";
// call delegate here.

Rappelez-vous aussi: Les chaînes sont internées dans le CLR. Même si le code a été dupliqué, les littéraux de chaîne seront internés dans un pool. Vous auriez essentiellement seulement une référence de taille de WORD natif qui pointait vers la chaîne (littéraux de chaîne seulement ..)


Answer #2

Vous devriez probablement utiliser la Task.Factory.StartNew(Action<object> action, object state) pour passer l'état dans votre nouvelle tâche.

Task.Factory.StartNew((object myState) => {
    var i = (int)myState;

    //Do calculations...
    var x = i + 10; 
}, 10);




task