Лямбда-выражения с многопоточностью в C # - PullRequest
4 голосов
/ 23 февраля 2012

Я пытаюсь понять, почему эта программа не работает

Ожидаемый результат: числа 0-19 в случайном порядке Что я получаю, когда бегу: некоторые цифры повторяются, иногда печатается 20.

Пожалуйста, помогите. Я пытался с блокировкой (obj) в DoSomething (), но это не помогло.

Программа

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication2
{
    public delegate void callbackDelegate(int x);
    class Program
    {
        void processCallback(int x)
        {
            Console.WriteLine("IN callback: The value I got is " + x);
        }

        static void Main(string[] args)
        {
            Program p = new Program();
            p.processinThreads();
            Console.ReadKey();
        }

        public void DoSomething(int x, callbackDelegate callback)
        {
            Thread.Sleep(1000);
            //Console.WriteLine("I just woke up now " + x);
            callback(x);
        }

        public void processinThreads()
        {
            for (int i = 0; i < 20; i++)
            {
                Thread t = 
new Thread(new ThreadStart(()=>DoSomething(i, processCallback)));
                t.Start();
            }
        }
    }
}

Ответы [ 3 ]

9 голосов
/ 23 февраля 2012
public void processinThreads()
{
    for (int i = 0; i < 20; i++)
    {
        int local = i;
        Thread t = new Thread(new ThreadStart(()=>DoSomething(local, processCallback)));
        t.Start();
    }
}

Ваша проблема связана с закрытием лямбды.

7 голосов
/ 23 февраля 2012

Вы должны просто использовать TPL, это намного проще и рекомендуется по сравнению с ручным управлением потоками :

Parallel.For(0, 20, x => {
    Thread.Sleep(1000);
    Console.WriteLine("IN callback: The value I got is " + x);
});

Это также будет блокировать до завершения цикла, если вы не хотите, чтобы вы могли использовать TPL Task, но я бы определенно рекомендовал избегать потоков.

1 голос
/ 23 февраля 2012

Как уже сказал вам Якуб, вам нужно скопировать i в другую локальную переменную local.В вашем коде делегаты имеют прямой доступ к самой i, а не к копии i, поэтому они распечатывают текущее значение i, которое может быть больше, чем при запуске потока.Это называется закрытием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...