0

I have created a console app which print the number in a for loop using C# Task.Run() method. If you look at the code, I am initializing the Employee object in the loop and pass the number in the method, though it prints the same number.

Code:

class Program
    {
        static void Main(string[] args)
        {
            for (int i = 1; i <= 500; i++)
            {
                Task.Run(() => new Employee().ProcessEmployee(i));
            }
            Console.Read();
        }
    }

    public class Employee
    {
        public void ProcessEmployee(int employeeId)
        {
            Console.WriteLine($"The number is: {employeeId} and thread is {Thread.CurrentThread.ManagedThreadId}");
        }
    }

Output:

enter image description here

The question is- How would I fix this issue? I still want to use Task.Run() method because in my real application scenarios, I want to process the stream (JSON data) in a different thread and do not want to block my main callback method which receive the stream (JSON data).

Thanks in advance.

nunu
  • 3,184
  • 10
  • 43
  • 58
  • Does this answer your question? [Task.Run with Parameter(s)?](https://stackoverflow.com/questions/30225476/task-run-with-parameters) – Manish Dec 31 '19 at 06:57

2 Answers2

2

By the time the task actually starts, the value of i has already incremented.

try assigning value of i to another variable and then pass that variable.

class Program
{
    static void Main(string[] args)
    {
        for (int i = 1; i <= 500; i++)
        {
            int j = i;
            Task.Run(() => new Employee().ProcessEmployee(j));
        }
        Console.Read();
    }
}

public class Employee
{
    public void ProcessEmployee(int employeeId)
    {
        Console.WriteLine($"The number is: {employeeId} and thread is {Thread.CurrentThread.ManagedThreadId}");
    }
}

Edit: duplicate/source : For Loop result in Overflow with Task.Run or Task.Start

Rishi Shah
  • 46
  • 6
1

This is because lambda capture variables, so they all refer to i, and by the time your task runs the for i is already at 501. You need to store a local variable within your for and copy the current value of i and use that in your lambda so that this specific variable (that is declared within the scope of the loop and thus a new variable each iteration) is the one that is captured

for(int i = ....)
{
    var tmp = i;
    Task.Run(() => new Employee().ProcessEmployee(tmp));
}
Ronan Thibaudau
  • 3,413
  • 3
  • 29
  • 78