0

Could someone explain me why this code is not working :

...
foreach (VisualChunk chunk in SortedChunks)
{
    System.Action a = () => MyFunction_Threaded(chunk);
    Console.Write("Synchronous : ");
    a.Invoke();
    System.Threading.Tasks.Task.Factory.StartNew(
                                        a,
                                        CancellationToken.None,
                                        TaskCreationOptions.None,
                                        TaskScheduler.Default)
} 
...

private void MyFunction_Threaded(VisualChunk chunk)
{
        Console.WriteLine(chunk.ChunkID);
}

It gives me the following output at console :

Synchronous : 0
Synchronous : 1
Synchronous : 2
Synchronous : 3
Synchronous : 4
Synchronous : 4294967291
Synchronous : 4294967292
Synchronous : 4294967293
Synchronous : 4294967294
Synchronous : 4294967295
Synchronous : 4294967296
Synchronous : 4294967297
4294967297
4294967297
4294967297
4294967297
4294967297
4294967297
4294967297
4294967297
4294967297
4294967297
4294967297
Synchronous : 4294967298
4294967298

In fact this code is working perfectly when .net framework 4.5 is installed (win 8 or VS2012). When only the 4.0 is installed, this problem is raising !

Fabian
  • 55
  • 6
  • 3
    Captured loop variable. Again... Search stack overflow for that term. This is clearly a flaw in the language considering how many people hit this problem. – usr Oct 15 '12 at 23:10
  • @usr I'd say it *was* a flaw in the language. It has been fixed in C# 5. – svick Oct 15 '12 at 23:39
  • @svick who knew?! Was this ever announced somewhere (apart from the spec)? I only knew they were considering this step, not that they actually took it. Kind of the most hidden new feature in C# 5. – usr Oct 15 '12 at 23:50
  • 1
    @usr I can't find anything official (even the [*What's New* page](http://msdn.microsoft.com/en-us/library/hh156499.aspx) doesn't mention it), but there is [an answer from Eric Lippert](http://stackoverflow.com/a/8899347/41071) (and the blog post where he talked about considering it was updated). – svick Oct 16 '12 at 00:16
  • In fact its not even linked to C# 5. As soon as your have .Net framework 4.5 installed the code will work perfectly (even in 4.0 compatibility mode). – Fabian Oct 16 '12 at 06:26
  • @Fabian You got that backwards. Even if you have .Net 4.5 installed, you will get the old behavior if you use VS 2010. But if you use VS 2012, you are using C# 5, even if you're compiling for .Net 4.0, so you will get the new behavior. – svick Oct 16 '12 at 18:24

1 Answers1

1

Yes, as mentioned in comments above by @usr, the problem in your code is that you have "modified closure," where the compiler is somewhat misinterpreting what you want to do when it builds the assembly language. It is a very poor design choice in the c# language. To get around it, you would need to make a copy of the variable in the loop right away:

foreach (VisualChunk chunk in SortedChunks)
{
  var chunkA = chunk;
  System.Action a = () => MyFunction_Threaded(chunkA);
  ...

However, I would have to ask what the point of this is (i.e. what are you trying to accomplish with this code)?

theMayer
  • 15,456
  • 7
  • 58
  • 90
  • Tx you for the answer. Where I was misleading was that I'm using a project with framework 4.0 requirement. Under Windows 8 or VS 2012 with Win 7 the code is working perfectly. But the same code under a Win 7 without 4.5 framework installed is raising the error. This code has no reason to be, it a very simplified sample (for the forum) for trying to explain the problem. – Fabian Oct 16 '12 at 06:26
  • I really think this "breaking" change should be more push forward by microsoft. I'm quite sure I won't be the first one to have a code running perfectly under C#5 that will fall in error under C#4. – Fabian Oct 16 '12 at 06:54