Die Datenweitergabe an einen Thread lässt sich relativ leicht durch den Einsatz von Lambda Expressions realisieren. Diese Daten können dabei Variablen der umschliessenden Methode sein, in welcher die Lambda Expression definiert wurde. Wie bereits in einem früheren Artikel gezeigt, wird der Wert der Variablen erst ausgewertet wenn die Lambda Expression aufgerufen wird. In einer Multithreading Anwendung kann dieses Verhalten aber dazu führen das ein falscher Wert als Parameter verwendet wird.
Der nachfolgende Quellcode zeigt ein entsprechendes Beispiel.
1 for (int i = 0; i < 10; i++)
2 {
3 new Thread(() => Console.Write(i + " ")).Start();
4 }
In einem Loop wird der Loopcounter jeweils in parallelen Threads ausgegeben. Erwartungsgemäss müssten somit die Zahlen von null bis neun in zufälliger Reihenfolge ausgegeben werden. Die Ausgabe kann dabei bei jeder Ausführung der Anwendung anders sein. Die Anwendung hat bei mir nachfolgende Ausgabe erzeugt:
2 3 4 4 6 8 8 8 8 10
Einige Werte sind mehrfach enthalten. Ausserdem ist der unerwartete Wert „10“ enthalten. Da die Variable erst bei der Ausführung der Lambda Expression ausgewertet wird ist dieses Verhalten gut erklärbar. Bis die eigentliche parallele Funktion gestartet wird, wird der Variablenwert im Loop bereits geändert.
Diesem Verhalten kann aber sehr leicht entgegengewirkt werden. Mittels einer temporären Variable kann jedem Thread ein individueller Funktionsparameter mitgegeben werden. Der nachfolgende Quellcode zeigt diese Anpassung.
1 for (int i = 0; i < 10; i++)
2 {
3 int value = i;
4 new Thread(() => Console.Write(value + " ")).Start();
5 }
In einem Test hat die Anwendung folgende Ausgabe erzeugt:
0 1 2 3 4 5 7 8 6 9
Jetzt werden die erwarteten Werte null bis neun in beliebiger Reihenfolge ausgegeben.
Fazit
In Multithreading Anwendungen sollten lokale Variablen nicht direkt in Lambda Expressions genutzt werden. Stattdessen sollten temporäre Variablen zum Einsatz kommen. Dies ist zwar nicht in jedem Szenario zwingend nötig, unterbindet aber von vornherein den hier angesprochenen Effekt und erspart Ihnen somit nächtelange Debug Sessions.