Нерестовые задачи внутри цикла for - PullRequest
0 голосов
/ 06 сентября 2018

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

static void Main(string[] args)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    Console.WriteLine("Main Started");
    MainChild(sw).Wait();
    Console.WriteLine("Main ended: "+sw.Elapsed);
}

static async Task MainChild(Stopwatch sw)
{
    Task[] tasks = new Task[100];
    for (int i = 0; i < 100; i++)
    {
        tasks[i] = Task.Factory.StartNew(new Action(async()=> {
            await Task.Delay(1000);
            Console.WriteLine("Task1 completed: " + sw.Elapsed);
        }));
    }

    await Task.WhenAll(tasks);
}

Я заметил, что основной поток выполняет: "Main Ended:" еще до выполнения задач. Почему это?

1 Ответ

0 голосов
/ 06 сентября 2018

Метод Task.Factory.StartNew устарел и почти никогда не использовался в наши дни, также он не понимает асинхронные делегаты .

Другое дело, что делегат Action возвращает void, а async void - это действие типа «забыл и забыл». Эта операция не возвращает Задачу и не ожидается.

Изменить Action:

tasks[i] = Task.Factory.StartNew(new Action(async () =>
{
    await Task.Delay(1000);
    Console.WriteLine("Task1 completed: " + sw.Elapsed);
})); 

К Func<Task> и Task.Run:

tasks[i] = Task.Run(new Func<Task>(async () =>
{
    await Task.Delay(1000);
    Console.WriteLine("Task1 completed: " + sw.Elapsed);
}));

Поскольку тип делегата определяется компилятором, мы можем сократить его до:

tasks[i] = Task.Run(async () => ...

Теперь он работает как положено и ожидает завершения всех задач

...