2010-08-05 3 views
2

Donc, j'ai une méthode qui obtient un dictionnaire de la liste <myObj>, puis cycles à travers les clés du dictionnaire et passe chaque liste <myObj> à un thread séparé.C# Thread Les paramètres changent pendant l'exécution du thread - pourquoi?

Voici une partie/Psuedo-Code:

public static void ProcessEntries() { 

    Dictionary<string, List<myObj>> myDictionary = GetDictionary(); 

    foreach(string key in myDictionary.keys) 
    { 

     List<myObj> myList = myDictionary[key]; 

     Thread myThread = new System.Threading.Thread(new System.Threading.ThreadStart(delegate() { 

      ProcessList(myList); 

     }  
    } 
} 

public static void ProcessList(List<myObj> myList) { 

    // Process entries 
    // read-only operations on myList 

} 

Le problème est que lors de l'exécution de processlist le paramètre myList change simplement. J'ai parcouru la liste avant de donner un coup de pied au thread, puis immédiatement à l'intérieur du thread, et j'ai trouvé que les résultats étaient différents.

J'ai depuis résolu le problème (je pense!) En rendant la variable Dictionary global. L'utilisation de la propriété [ThreadStatic] est la prochaine sur la liste des correctifs possibles. Ce que je veux vraiment savoir, c'est pourquoi l'objet myList change dans ProcessList() probablement lorsque l'objet myList est réattribué dans ProcessEntries()? Ce ne sont pas deux listes différentes? Si tous les paramètres passent par valeur par défaut, pourquoi la fonction ProcessList() n'a-t-elle pas de copie locale de myList? (le fait-il?)

Existe-t-il un moyen de spécifier que vous voulez passer un paramètre à un thread et ne pas avoir à être modifié par le thread parent ou d'autres threads pendant l'exécution? (Ceci serait similaire à l'attribut [ThreadSafe] pour les variables globales)

+1

Etes-vous sûr que votre code/code-source est correct et complet? D'après ce que je peux voir, alors que vos hypothèses sur ce qui se passe sont fausses, il semble que le code devrait fonctionner correctement. –

Répondre

0

Vous passez un référence en valeur dans ce cas, donc si vous le modifiez quelque part, il sera différent chaque fois.

2

Je soupçonne que votre pseudo-code n'est pas réellement un reflet exact de votre vrai code. Je soupçonne que votre réel du code ressemble à ceci:

foreach(var pair in myDictionary) 
{ 
    Thread myThread = new Thread(delegate() { 
     ProcessList(pair.Value); 
    }); 
    myThread.Start(); 
} 

Si tel est le cas, le problème est que la variable pair est capturée - donc au moment où votre fil démarre, il peut se référer à une autre touche/paire de valeurs.

La façon de le fixer est de rendre le code plus précisément comme votre pseudo-code:

foreach(var pair in myDictionary) 
{ 
    // You'll get a new list variable on each iteration 
    var list = pair.Value; 
    Thread myThread = new Thread(delegate() { 
     ProcessList(list); 
    }); 
    myThread.Start(); 
} 

Voir Eric Lippert's blog post on this pour plus d'informations.

Si ce n'est pas ce qui ne va pas, donnez un exemple réel plutôt qu'un pseudo-code. Un short but complete example demonstrating the problem serait idéal.

1

Assurez-vous également que les autres threads n'affectent pas le thread que vous essayez d'utiliser. assurez-vous d'utiliser des verrous et des moniteurs ... Vous avez eu quelques problèmes avec cela il y a quelques semaines à peine.

Questions connexes