Selalu_Ingin_Belajar
Selalu_Ingin_Belajar

Reputation: 375

Parallel Task resulting wrong result

Why List of Task resulting wrong result. Anyone can give direction?

This my code so far.

static string[] kk = new string[] { "a", "b", "c", "d", "e", "f" };

static void Main(string[] args)
    {
        //Parallel.For(0, 10, i => Test(i));
        //Console.ReadLine();

        foreach(string str in kk)
        {
            Task<string> task = Task.Factory.StartNew(() => Test(str));
            listTask.Add(task);
        }

        do
        {
            Thread.Sleep(100);
        }while(!Task.WaitAll(listTask.ToArray(),1000));

        foreach (Task<string> task in listTask)
        {
            Console.WriteLine(task.Status.ToString() + " : " + task.Result);
        }

        Console.ReadLine();
    }

 private static string Test(string i)
        {
             return "test " + i;
        }

I expecting result like this:

test a test b test c test d test e test f

But my code above resulting like this: test f test f test f test f test f test f

Thanks in advance.

Upvotes: 0

Views: 662

Answers (1)

dcastro
dcastro

Reputation: 68760

This line is the culprit:

Task<string> task = Task.Factory.StartNew(() => Test(str));

The lambda expression, which captured the str variable, is only evaluated when the Task is run.

In this case, the task's threads were activated once the foreach loop finished - which means Test(str) will be evaluated as Test("f") for all six calls. This happens because the foreach implementation reuses the str variable for all iterations, and so all six lambda expressions captured the same variable.

Try changing it to:

var localStr = str;
Task<string> task = Task.Factory.StartNew(() => Test(localStr));

This will make it so that each expression captures its own local variable.

Edit:

This issue was fixed in C# 5: Has foreach's use of variables been changed in C# 5?

Each foreach iteration now gets a fresh copy of the variable.

Upvotes: 2

Related Questions