Max Bündchen
Max Bündchen

Reputation: 1362

Async Task with sync method call

I'm starting with the new .net 4.5 async programming and I found a situation like the code below: I have a sync method but I would like to make several calls and make it run in parallel. However, in this code, all the calls to the sync method runs with the id = 10 and I'm not sure why (probably I misunderstand something with this new approach :).

class Program
{
    static void Main(string[] args)
    {
        var tasks = new List<Task>();

        for (int i = 0; i < 10; i++)
        {
            var foo = new Foo();
            var fooTask = Task.Run(() => foo.FooNonAsyncMethod(i));
            tasks.Add(fooTask);
        }
        tasks.ForEach(t => t.Wait());

        Console.WriteLine("All Done!");

        Console.ReadLine();
    }
}

public class Foo
{
    public void FooNonAsyncMethod(int id)
    {
        Console.WriteLine("Starting {0}", id);

        Thread.Sleep(4000);

        Console.WriteLine("Ending {0}", id);
    }
}

// Output:

// Starting 10
// Starting 10
// Starting 10
// Starting 10
// Ending 10
// Starting 10
// Starting 10
// Ending 10
// Ending 10
// ...

Upvotes: 1

Views: 704

Answers (1)

Bun
Bun

Reputation: 1495

That's because there is only 1 variable i and the lambda expressions bind on a variable and not a value.

You can fix this by using:

for (int i = 0; i < 10; i++)
{
    int newI = i;
    var foo = new Foo();
    var fooTask = Task.Run(() => foo.FooNonAsyncMethod(newI));
    tasks.Add(fooTask);
}

As @Yuriy mentioned, this answer has a lot more info on this particularity : Is there a reason for C#'s reuse of the variable in a foreach?

Upvotes: 4

Related Questions