Добрый вечер, пытаюсь с помощью Task создать несколько процессов и запустить функцию в каждом из них, но всегда получается одинаковая итерация. Вот пример кода:

var Task_1 = Task.Factory.StartNew(() =>
{
for (var i = 0; i < 7; i++)
{
Task.Factory.StartNew(() =>
{
Console.WriteLine(i);

//Task.Factory.StartNew(matrix.Multiplication, i, TaskCreationOptions.AttachedToParent);

}, TaskCreationOptions.AttachedToParent);

}
});

Task.WaitAll(Task_1);

На экране не выводится 7 различных цифр в какой-либо последовательности, при последней компиляции вывелась одна четверка и все остальные семерки. Объясните кто-нибудь в чем проблема и как это обойти? Я пробовал в цикле ожидать завершении каждого процесса (пример: task.Wait()), но тогда уже ведь задача не является параллельной.

задан 7 дек ’15 в 18:20

Проблема в том, что i — переменная! А значит, её значение меняется. Когда задача начинает выполняться, значение i уже вполне может измениться. А вы ведь выводите всё время одну и ту же переменную i.

Я бы написал так:

Task Output(int i)
{
return Task.Run(() => Console.WriteLine(i));
}

var tasks = new List<Task>();
for (int i = 0; i < 7; i++)
tasks.Add(Output(i));
await Task.WhenAll(tasks);

При этом значение i копируется в момент вызова функции.

ответ дан 7 дек ’15 в 18:25

В свое время сталкивался с этой проблемой. Объяснение нашел на английском SO. К сожалению не могу найти ссылку. Вынесите переменную в локальную итерацию, примерно так:

var th = Task.Factory.StartNew(() =>
{
for (var i = 0; i < 7; i++)
{
int localVar = i;

Task.Factory.StartNew(() =>
{
Console.WriteLine(localVar);

}, TaskCreationOptions.AttachedToParent);
}
});

ответ дан 7 дек ’15 в 18:24

Спасибо всем, вроде разобрался, решил проблему следующим образом:

var Task_1 = Task.Factory.StartNew(() =>
{

Task.Factory.StartNew(() =>
{

for (int j = 0; j <= Environment.ProcessorCount – 1; j++)
{

Console.WriteLine(j);
//Task.Factory.StartNew(matrix.Multiplication, j, TaskCreationOptions.AttachedToParent);

}

}, TaskCreationOptions.AttachedToParent);

});

Task.WaitAll(Task_1);

ответ дан 7 дек ’15 в 18:29

Всё ещё ищете ответ? Посмотрите другие вопросы с метками c# task или задайте свой вопрос.