{"id":405,"date":"2012-12-12T14:35:30","date_gmt":"2012-12-12T13:35:30","guid":{"rendered":"http:\/\/www.martyndavis.com\/?p=405"},"modified":"2013-03-20T16:50:03","modified_gmt":"2013-03-20T15:50:03","slug":"lamba-expressions-and-threads-in-c","status":"publish","type":"post","link":"https:\/\/www.martyndavis.com\/?p=405","title":{"rendered":"Lambda Expressions and Threads in C#"},"content":{"rendered":"<p>Here&#8217;s a small program&#8230; what do you think the output will be?<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static void Main(string&#x5B;] args){\r\n    Thread&#x5B;] t = new Thread&#x5B;10];\r\n    for (int tNum = 0; tNum &lt; 10; tNum++) {\r\n        t&#x5B;tNum] = new Thread(() =&gt; {\r\n            Thread.Sleep(new Random().Next(20));\r\n            Console.Write(tNum + &quot; &quot;);\r\n        });\r\n        t&#x5B;tNum].Start();\r\n    }\r\n    \/\/ wait for the threads to finish\r\n    for (int tNum = 0; tNum &lt; 10; tNum++){\r\n        t&#x5B;tNum].Join();\r\n    }\r\n    Console.WriteLine(&quot;\\nPress a key...&quot;);\r\n    Console.Read();\r\n}\r\n<\/pre>\n<p><!--more-->If some of it is gobbledegook to you, let me take a moment to explain what&#8217;s going on. \u00a0Lines 4-7 create a thread using Lambda expressions &#8211; we&#8217;re essentially putting the code we want to execute in each Thread in-line. Lambda expressions can &#8220;see&#8221; variables in the scope in which they are defined, hence \u00a0we can reference the loop counter tNum inside the Lambda.<\/p>\n<p>So, what did you think the output would be?<\/p>\n<p>When I was writing something that used a similar construct to this I&#8217;d have said it should be the numbers 0-9 inclusive in a random order (because the threads are sleeping for a random time), e.g.:<\/p>\n<pre>0 1 2 3 6 7 4 5 8 9<\/pre>\n<p>I was wrong! Here&#8217;s what I just got from running the above code:<\/p>\n<pre>1 1 4 8 8 9 8 10 10 10<\/pre>\n<p>Huh? Apart from the fact that some numbers are missing and some are repeated, we&#8217;ve got<strong> 10<\/strong> as a value &#8211; where the for loop specifically has &#8220;&lt; 10&#8221; as its while clause.<\/p>\n<p>If this baffles you like it did me initially, let me explain!<\/p>\n<p>The way Lambda expressions work mean even though tNum is an int and hence a value type, when it is <em>captured<\/em> in the Lambda expression, it acts as if it is of Reference type (it&#8217;s actually not, behind the scenes, but it&#8217;s the easiest way to think about it). This means we&#8217;ve fired off a thread with something that behaves as a\u00a0<strong>reference<\/strong>\u00a0to tNum. As the thread is busy doing something (or in this case pretending to do something by sleeping for a random time), the main thread&#8217;s for() loop is busy incrementing the value that tNum holds. This explains why we&#8217;ve got random-looking numbers coming out. And the value 10 is explained by the fact that once the for() loop finished, the last increment took tNum to 10, which terminated the loop.<\/p>\n<p>To fix this kind of problem, it helps to use a variable that isn&#8217;t going to change. Here&#8217;s the fixed version:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static void Main(string&#x5B;] args)\r\n{\r\n    Thread&#x5B;] t = new Thread&#x5B;10];\r\n    for (int tNum = 0; tNum &lt; 10; tNum++) {\r\n        int n = tNum; \/\/ new line\r\n        t&#x5B;tNum] = new Thread(() =&gt; {\r\n            Thread.Sleep(new Random().Next(20));\r\n            Console.Write(n + &quot; &quot;); \/\/ changed line\r\n        });\r\n        t&#x5B;tNum].Start();\r\n    }\r\n    \/\/ wait for the threads to finish\r\n    for (int tNum = 0; tNum &lt; 10; tNum++) {\r\n        t&#x5B;tNum].Join();\r\n    }\r\n    Console.WriteLine(&quot;\\nPress a key...&quot;);\r\n    Console.Read();\r\n}\r\n<\/pre>\n<p>On line five we&#8217;re now taking a copy of tNum, and we&#8217;re referencing that instead in the Lambda. Hey presto, we now get expected output.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here&#8217;s a small program&#8230; what do you think the output will be? public static void Main(string&#x5B;] args){ Thread&#x5B;] t = new Thread&#x5B;10]; for (int tNum = 0; tNum &lt; 10; tNum++) { t&#x5B;tNum] = new Thread(() =&gt; { Thread.Sleep(new Random().Next(20)); Console.Write(tNum + &quot; &quot;); }); t&#x5B;tNum].Start(); } \/\/ wait for the threads to finish for &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.martyndavis.com\/?p=405\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Lambda Expressions and Threads in C#&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14,1],"tags":[],"_links":{"self":[{"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=\/wp\/v2\/posts\/405"}],"collection":[{"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=405"}],"version-history":[{"count":18,"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=\/wp\/v2\/posts\/405\/revisions"}],"predecessor-version":[{"id":428,"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=\/wp\/v2\/posts\/405\/revisions\/428"}],"wp:attachment":[{"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=405"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=405"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=405"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}