Commencer un nouveau thread dans une boucle foreach
J'ai une Liste d'objets, et j'aimerais faire une boucle sur la liste et commencer un nouveau fil, le passer dans l'objet courant.
J'ai écrit un exemple de ce que je pensais faire ceci, mais ça ne fonctionne pas. Plus précisément, il semble que les fils sont écrasés à chaque itération. Ce n'est pas vraiment de sens pour moi si, car je suis en train de faire un nouvel objet Thread à chaque fois.
C'est le test de code que j'ai écrit
class Program
{
static void Main(string[] args)
{
TestClass t = new TestClass();
t.ThreadingMethod();
}
}
class TestClass
{
public void ThreadingMethod()
{
var myList = new List<MyClass> { new MyClass("test1"), new MyClass("test2") };
foreach(MyClass myObj in myList)
{
Thread myThread = new Thread(() => this.MyMethod(myObj));
myThread.Start();
}
}
public void MyMethod(MyClass myObj) { Console.WriteLine(myObj.prop1); }
}
class MyClass
{
public string prop1 { get; set; }
public MyClass(string input) { this.prop1 = input; }
}
La sortie sur ma machine est
test2
test2
mais je m'attendais à être
test1
test2
J'ai tenté de changer le fil des lignes à
ThreadPool.QueueUserWorkItem(x => this.MyMethod(myObj));
mais aucun des threads commencé.
Je pense que j'ai juste un malentendu au sujet de la façon dont les threads sont censés travailler. Quelqu'un peut me pointer dans la bonne direction et dites-moi ce que je fais mal?
- Votre vie sera beaucoup plus facile si vous découvrez le Parallèle de la Bibliothèque d'Extensions introduites dans .Net 3.5. Voici un endroit pour commencer: msdn.microsoft.com/en-us/library/dd460693%28VS.100%29.aspx
- albahari.com/threading
Vous devez vous connecter pour publier un commentaire.
C'est parce que vous êtes à la clôture sur une variable dans le mauvais champ d'application. La solution ici est d'utiliser une temporaire dans votre boucle foreach:
Pour plus de détails, je vous recommande la lecture d'Eric Lippert post sur ce sujet précis: La fermeture de plus de la variable de boucle considéré comme nocif
Le problème est que vous utilisez le plus courant de la valeur de l'objet à l'intérieur de votre fermeture. Ainsi, à chaque invocation du fil est à la recherche à la même valeur. Pour contourner ce problème, copiez la valeur dans une variable locale:
D'accord avec Reed réponse (+1).
Je voudrais ajouter que si vous êtes sur .NET 4, vous pouvez regarder la Task Parallel Library pour résoudre cette classe de problème. Plus précisément pour ce cas, jetez un oeil à En parallèle.ForEach().
si la séquence n'est pas question que d'aller pour
Écrire un Simple Parallèle.Boucle ForEach
Je préfère cette façon:
pas testé mais....