Несколько тяжелых методов средствами 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 шт):
Классика, решается кешированием переменных. Делегат захватывает именно ссылки, поэтому очень простой фикс нужен.
int x1 = x, y1 = y;
loadThreads[x * size.x + y] = Observable.Start(() =>
{
Debug.Log("x: " + x1 + " y: " + y1);
});
То есть мысль верная была, но вы это делали в делегате, а надо было за его пределами.
