Несколько тяжелых методов средствами UniRx

Использую ассет UniRx для того чтобы что то считать в других потоках. Использовал эту вот статью, в ней в разделе "Пример обработки сложных методов" написано как выполнять несколько тяжеловесных задач в разных потоках.

Так вот я пытаюсь обработать матрицу по кускам, по потоку на каждый блок, поделив ее 7х7, для примера просто вывожу Debug.Log():

/// Кол-ва блоков
Vector2Int size = new Vector2Int(7, 7);

/// Храним методы
System.IObservable<Unit>[] loadThreads = 
    new System.IObservable<Unit>[size.x * size.y];

for (int x = 0; x < size.x; x++)
    for (int y = 0; y < size.y; y++)
    {
        loadThreads[x * size.x + y] = Observable.Start(() =>
        {
            Debug.Log("x: " + x + " y: " + y);

            // такой же эффект
            //int x1 = x, y1 = y;
            //Debug.Log("x: " + x1 + " y: " + y1);

            return;
        });
    }

/// Работаем
Observable.WhenAll(loadThreads).
    ObserveOnMainThread().Subscribe(result =>
    {
        Debug.Log("Finish");
    });

Что в итоге дает эффект как будто x и y передались ссылками и у меня везде конечные индексы + 1, как будто цикл кончился, в конце прибавил еще один индекс и в итоге другой поток обращается в память где эти x и y с циклов и видит там 7-рки...

введите сюда описание изображения

Я в многопоточности очень слаб, помогите подскажите как правильно реализовать решение?

PS: Возможно нужно решать задачу другими средствами? Мне в голову пришло сразу то, как в майнкрафте карта генерится по кругу, может нужно какую то Queue с индексами? Я не понимаю, пните хотя бы меня в нужную сторону мысления


Ответы (1 шт):

Автор решения: aepot

Классика, решается кешированием переменных. Делегат захватывает именно ссылки, поэтому очень простой фикс нужен.

int x1 = x, y1 = y;
loadThreads[x * size.x + y] = Observable.Start(() =>
{
    Debug.Log("x: " + x1 + " y: " + y1);
});

То есть мысль верная была, но вы это делали в делегате, а надо было за его пределами.

→ Ссылка