При старте приложения надо запустить фоном выполнение нескольких тяжеловесных методов
Имеем:
var first = new Action(() => {});
var after1 = new Action(() => {});
var after2 = new Action(() => {});
...
var afterN = new Action(() => {});
Нужно дождаться выполнения метода first и запустить параллельно все остальные
Сейчас это работает так:
var _afters =
{
new Task(after1),
new Task(after2),
...
new Task(afterN),
}
var task = Task.Run(() => first).ContinueWith(t =>
{
_afters.ForEach(a => a.Start());
Task.WaitAll(_afters);
});
Можно ли написать как-то покрасивее?
Спасибо...
Re: Как правильно вызвать последовательность задач?
Здравствуйте, Nikolay_Ch, Вы писали: D>>Можно ли написать как-то покрасивее? N_C>А покрасивее — это как? Что смущает?
в 1 оператор
и не стартовать задачи из массива руками
в примерах вроде можно стартовать 1 задачу, остальные как-то подтягиваются
а у меня так не получается
Re[2]: Как правильно вызвать последовательность задач?
Здравствуйте, mDmitriy, Вы писали:
D>в 1 оператор
В один оператор — это все равно будет набор операторов, умещенных в одну строку (см. мой пример)
D>в примерах вроде можно стартовать 1 задачу, остальные как-то подтягиваются
В каких примерах? Покажите. Что значит "как-то"? Примеры надо разбирать, чтобы понимать это "как-то"
Re[3]: Как правильно вызвать последовательность задач?
Здравствуйте, karbofos42, Вы писали:
K>Вместо _afters завести ActionBlock?
Разные же анонимные методы для задач, а ActionBlock работает только с одним. Да и ActionBlock переходит в ошибку после первого эксепшина и не выполняет оставшуюся очередь — подойдет ли это топик стартеру.
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
Re[2]: Как правильно вызвать последовательность задач?
Здравствуйте, _Raz_, Вы писали:
_R_>Здравствуйте, karbofos42, Вы писали:
K>>Вместо _afters завести ActionBlock?
_R_>Разные же анонимные методы для задач, а ActionBlock работает только с одним. Да и ActionBlock переходит в ошибку после первого эксепшина и не выполняет оставшуюся очередь — подойдет ли это топик стартеру.
Ну, какую-нибудь такую штуку можно написать: ActionBlock<Action>((a) => a.Invoke()). Но для этого конечно Parallel.Invoke логичнее использовать.
Как я понял по описанию Parallel.Invoke, получится, что ContinueWith запускает Parallel.Invoke и ждет, пока он отработает(т.е. таска ContinueWith будет периодически получать время на выполнение, даже если не все задачи завершены).
Если же сделать как-нибудь через await
Здравствуйте, StatujaLeha, Вы писали:
SL>то таска ContinueWith запустит все задачи и в следующий раз будет разбужена только по завершении всех задач.
Э... Что? Первая таска завершится и после нее начнет выполнятся вторая таска. Вторая будет в состоянии ожидания, пока Parallel не завершится.
По-моему разницы быть не должно.
Здравствуйте, Nikolay_Ch, Вы писали:
N_C>Э... Что? Первая таска завершится и после нее начнет выполнятся вторая таска. Вторая будет в состоянии ожидания, пока Parallel не завершится. N_C>По-моему разницы быть не должно.
Есть тредпул. Потоки из него обрабатывают таски.
Идеальный вариант:
1. Приходим в таску ContinueWith и запускаем все нужные таски after.
2. Ставим на паузу таску ContinueWith.
3. Ждем, пока все таски after завершатся.
4. Идем обратно в таску ContinueWith и завершаем ее.
Т.е. мы тратим на таску ContinueWith ресурсы только тогда, когда оно реально необходимо.
В примере через await оно так и должно работать.
А вот в варианте через Parallel это мне непонятно...
Пришли мы к вызову Parallel.Invoke, запустили все таски after.
И как тредпул теперь поймет, что до завершения всех тасков after не надо тратить вычислительные ресурсы на таску, из которой запущен Parallel.Invoke?
Здравствуйте, StatujaLeha, Вы писали:
SL>И как тредпул теперь поймет, что до завершения всех тасков after не надо тратить вычислительные ресурсы на таску, из которой запущен Parallel.Invoke?
Посмотрите в исходники.Net... Там есть несколько вариантов работы Invoke, в зависимости от количества переданных Action'ов... Один из которых WaitAll, другой — FastWaitAll...