#c#
#c#
Вопрос:
У меня есть список из 100 значений
Я хочу создать 5 потоков для обработки 20 каждый
мой код в основном
for (int i = 0; i<5; i )
{
Task.Run(() => {
myMethod(myList.Skip(i * 20).Take(20)));
});
}
Очевидно, что, поскольку это закрывает значение i, это может полностью все испортить. Я перепробовал все, что мог придумать, чтобы заставить его фиксировать значение во время объявления задачи, но мне совсем не повезло. Даже установка первой строки задачи.Запустить var localVariable = i;
, чтобы захватить его, не работает, он запускает метод, и каждый раз i равен 5.
Как мне это сделать, предположительно, я хочу создать задачу, передав значение i, чтобы она никогда не выходила за пределы функции, но я не могу понять, как это сделать.
Есть идеи?
Ответ №1:
Вы почти на месте, но помимо создания копии локальной переменной, вам нужно использовать ее в своем лямбда-выражении:
for (int i = 0; i < 5; i )
{
int localCopy = i;
Task.Run(() => {
myMethod(myList.Skip(localCopy * 20).Take(20)));
});
}
Если это не работает, то проблема не в захвате переменной, а в другом месте.
Конечно, другой вариант — использовать Parallel.ForEach
с пользовательским разделителем или что-то в этом роде. Другими словами, вполне могут быть лучшие способы решения проблемы.
Комментарии:
1. Да, это не работает. Я предполагаю, потому что цикл настолько быстр, что он выполняет Task.Run 5 раз, прежде чем он даже получит возможность выполнить один раз.
2. @SLC: «не работает» не дает нам никакой информации, но это определенно работает с точки зрения выполнения 5 задач, одна из которых будет вызывать
Skip(0)
, одна из которых будет вызыватьSkip(20)
, одна из которых будет вызыватьSkip(40)
и т.д. Как я уже сказал в ответе, если этот код не работает, вам нужно искать проблему в другом месте. (У нас недостаточно контекста, чтобы помочь дальше …)3. Кажется, это временная проблема, возможно, она исправлена. Можете ли вы объяснить, почему это работает, если планировщик задач должен был запустить первую задачу, выполнить итерацию и запустить 2-ю задачу, а затем планировщик задач переключается на первую задачу и выполняет первую строку кода, конечно, я был бы 1 или 2 или более в зависимости от того, в какой момент он переключилсякому?
4. Я думаю, вы правы в том, что реальная проблема заключается в другом, я подозреваю, что myMethod делает некоторые небезопасные для потоков вещи. Я предполагаю, что c # должен закрывать переменную во время определения задачи, разумно определяя, какие переменные нам понадобятся в задаче?
5. @SLC: в моей копии кода
i
вообще не используется в задаче. Вместо этого используется копия значенияi
для этой итерации. Я не совсем уверен, о чем вы спрашиваете во втором комментарии, но компилятор C # учитывает область видимости, поэтомуlocalCopy
на первой итерации цикла является отдельной переменной дляlocalCopy
второй итерации цикла. Лямбда-выражение будет захватывать разные переменные.
Ответ №2:
Попробуйте установить var localVariable = i
вне задачи.