Выполнение задачи зависит от механизма ожидания? - PullRequest
0 голосов
/ 17 апреля 2019

Вот псевдокод, который я запускаю:

Вариант № 1:

List<Task> tasks = new List<Task>();
foreach (...)
{
    Task task = Task.Run(() =>
    {
        doWork();
    });
    tasks.Add(task);
}

Task.WhenAll(tasks.AsParallel()).ContinueWith((t) =>
{
    // process results/handle errors
    ...
});

Вариант № 2:

List<Task> tasks = new List<Task>();
foreach (...)
{
    Task task = Task.Run(() =>
    {
        doWork();
    });
    tasks.Add(task);
}

Task.WhenAll(tasks.AsParallel()).Wait();

// process results/handle errors
...

Мой вопрос такой,почему способ doWork вызывается радикально отличается между # 1 и # 2?Это из-за замысла, и я просто не понимаю, как это должно работать?

Мое (очевидно, ошибочное) понимание / предположение состояло в том, что doWork будет вызываться в многопоточном / асинхронном режиме, параллельно-if-доступно, в обоих сценариях, единственное отличие состоит в том, что вызывающий код будет ожидать завершения по-разному.Но то, как задачи на самом деле выполняются , будет одинаковым, потому что они запланированы / «запущены» одинаково.

Но из того, что я могу сказать после отладки обеих версий кода,вариант # 1 приводит к тому, что doWork вызывается в истинно параллельном / полностью многопоточном режиме, тогда как вариант # 2, кажется, действует как однопотоковое, последовательное выполнение каждой задачи.

Что яотсутствует

1 Ответ

3 голосов
/ 17 апреля 2019

.AsParallel() является LINQ многопоточным расширением, оно не имеет ничего общего с Task.Task.Run(...) само по себе достаточно для большинства случаев и может использоваться с LINQ.

или без него. Смешивать как AsParallel(), так и Task.Run() довольно опасно, если вы не уверены, что делаете:без каких-либо усилий это может значительно ухудшить вашу производительность, а не сделать ее лучше, как вы ожидаете.

Наконец, не Wait() Task: он будет принудительно выполняться регулярно и синхронно, тем самым отменяя все преимущества Task.

...