linq lambdas如何在循环中工作?

Ily*_*gin 2 c# linq lambda multithreading

我正在尝试在我的应用程序中实现任务.

这是示例代码:

有一个简单的接口我,3个类派生它(A,B,C)我创建一个Is的列表,用A,B,C实例poplualte,然后为对方创建一个任务来调用方法do1() ;

  interface I
    {
        void do1();

    }

    class A : I
    {
        public void do1()
        {
            Console.WriteLine("A");
        }
    }


    class B : I
    {
        public void do1()
        {
            Console.WriteLine("B");
        }
    }


    class C : I
    {
        public void do1()
        {
            Console.WriteLine("C");
        }
    }

    class Program
    {
        public static void Main(string[] args)
        {
            List<I> l = new List<I>();
            l.Add(new A());
            l.Add(new B());
            l.Add(new C());


            var TaskPool = new List<Task>();


            foreach (var i in l)
            {
                Task task = new Task( () => i.do1()

                    );
                TaskPool.Add(task);
            }


            foreach (var c in TaskPool)
            {
                c.Start();
            }

            Thread.Sleep(3000);
            Console.Read();
        }


    }
Run Code Online (Sandbox Code Playgroud)

我期待着看到

A
B
C
Run Code Online (Sandbox Code Playgroud)

在输出中,而不是我得到的

C
C
C
Run Code Online (Sandbox Code Playgroud)

我在调试器中找到了问题:所有任务都有相同的委托,但我不知道为什么以及如何解决这个问题.

Mar*_*ell 7

这是一个非常常见的问题.它涉及"捕获的变量"如何工作; 简短版本,你需要这个:

foreach (var i in l)
{
    var copy = i;
    Task task = new Task( () => copy.do1());
    TaskPool.Add(task);
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是i(来自foreach)在技术上声明在循环范围之外,因此在该外部范围被捕获; 每次捕获相同的变量(C#捕获变量,而不是*值).copy 在循环范围内添加会改变这一点; 因为范围,每次迭代都会copy单独捕获.

  • @portland:它是`i`*的*值的副本,无论该值是什么......无论是引用还是值类型值. (2认同)

Bri*_*sen 5

问题是您i在分配委托时捕获循环变量.如果在分配之前创建临时副本,则可以避免捕获变量,从而获得所需的值.

foreach (var i in l)
{
    var local = i;
    Task task = new Task( () => local.do1());
    TaskPool.Add(task);
}
Run Code Online (Sandbox Code Playgroud)