为什么C#Task.Run()方法在控制台应用程序的循环中打印相同的数字?

时间:2019-12-31 06:39:24

标签: c# multithreading asynchronous parallel-processing task-parallel-library

我创建了一个控制台应用,该应用使用C# Task.Run()方法在for循环中打印数字。如果您看一下代码,尽管循环中会打印相同的数字,但我正在循环中初始化Employee object并在方法中传递数字。

代码:

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}");
        }
    }

输出:

enter image description here

问题是-如何解决此问题?我仍然想使用Task.Run()方法,因为在我的实际应用场景中,我想在其他线程中处理流(JSON数据),并且不想阻塞接收流(JSON数据)的主回调方法

谢谢。

2 个答案:

答案 0 :(得分:2)

到任务实际开始时,i的值已经增加。

尝试将i的值分配给另一个变量,然后传递该变量。

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}");
    }
}

编辑:重复/来源:For Loop result in Overflow with Task.Run or Task.Start

答案 1 :(得分:1)

这是因为lambda捕获变量,所以它们都引用i,并且在您的任务运行for i的时间已经在501。您需要在for中存储局部变量并复制i的当前值,并在您的lambda中使用该值,以使该特定变量(在循环范围内声明,因此每次迭代均声明一个新变量)为捕获的变量

for(int i = ....)
{
    var tmp = i;
    Task.Run(() => new Employee().ProcessEmployee(tmp));
}
豫ICP备18024241号-1