Есть ли общая задача.WaitAll?


Я запустить несколько параллельных задач, как это:

var tasks =
    Enumerable.Range(1, 500)
    .Select(i => Task.Factory.StartNew<int>(ProduceSomeMagicIntValue))
    .ToArray();

и затем присоединиться к ним с

Task.WaitAll(tasks);

на этой последней строке я получаю синий волнистый маркер под tasks, с предупреждением:

Co-variant array conversion from Task[] to Task[] 
can cause run-time exception on write operation.

Я понимаю, почему я получаю это сообщение, но есть способ обойти это? (например, как общая версия Task.WaitAll()?)

3   51   2012-04-06 17:24:24

3 ответа:

для этого можно создать метод расширения.

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

static class TaskExtensions
{
    public static void WaitAll<T>(this Task<T>[] tasks)
    {
        foreach (var item in tasks)
        {
            item.Wait();
        }
    }
}

затем позвоните, из вашего текущего кода:

tasks.WaitAll();

Edit

фактическая реализация немного сложнее. Я опустил код из этого ответа, потому что это справедливо длинный.

http://pastebin.com/u30PmrdS

вы можете изменить это для поддержки общих задач.

Я уверен, что это безопасная работа даже с предупреждением, но если вы действительно хотите обойти его, лучший вариант, чем создание собственной реализации, - это просто преобразовать ваш tasks параметр в тип, который он хочет:

Task.WaitAll(tasks.Cast<Task>().ToArray())

это убивает синие закорючки для меня, позволяет мне сохранить мой tasks переменная generic и не заставляет меня создавать много нового страшного кода, который в конечном счете не нужен.

общий метод задачи.WaitAll подразумевал бы, что все задачи должны были бы возвращать один и тот же тип, который был бы чрезвычайно ограничен полезностью. Написание чего-то подобного можно было бы сделать вручную (см. ответ Bas Brekelmans), но это не позволит продолжить или отменить без большого количества работы.

простое решение, если вы не используете массив для все остальное

  .ToArray<Task>();