Re[12]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 14.09.17 20:54
Оценка: +2
Здравствуйте, Nikolay_Ch, Вы писали:

N_C>Не делает, но (судя по исходникам) и параллельно задачи не запускает, т.е. выполняет их последовательно одну за одной...


Он их вообще не запускает.

Поэтому в моем примере туда передаются задачи из Task.Run, т.е. уже запущенные(это обеспечит параллельность).
Task.WhenAll(Task.Run(after1), Task.Run(after2), Task.Run(after3))


А вот если сделать так, то ожидание будет вечным :D
Task.WhenAll(new Task(after1), new Task(after2), new Task(after3)).Wait()
Re[2]: Как правильно вызвать последовательность задач?
От: Nikolay_Ch Россия  
Дата: 13.09.17 09:16
Оценка: 3 (1)
Здравствуйте, _Raz_, Вы писали:

_R_>Здравствуйте, mDmitriy, Вы писали:


D>>Можно ли написать как-то покрасивее?


_R_>
_R_>  await first();
_R_>  Parallel.Invoke(
_R_>    () => {},
_R_>    () => {},
_R_>    () => {},
_R_>  );
_R_>

Можно оставить и без await:
var _afters = new[] { after1, after2, after3, after4, after5 };
Task.Run(()=>first).ContinueWith((t)=>Parallel.Invoke(_afters));
Re: Как правильно вызвать последовательность задач?
От: _Raz_  
Дата: 13.09.17 09:01
Оценка: +1
Здравствуйте, mDmitriy, Вы писали:

D>Можно ли написать как-то покрасивее?


  await first();
  Parallel.Invoke(
    () => {},
    () => {},
    () => {},
  );
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
Re[3]: Как правильно вызвать последовательность задач?
От: _Raz_  
Дата: 13.09.17 09:22
Оценка: +1
Здравствуйте, Nikolay_Ch, Вы писали:

N_C>Можно оставить и без await:


Можно, но тогда лучше с Then.
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
Как правильно вызвать последовательность задач?
От: mDmitriy Россия  
Дата: 13.09.17 08:40
Оценка:
Все привет!

При старте приложения надо запустить фоном выполнение нескольких тяжеловесных методов
Имеем:
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 Россия  
Дата: 13.09.17 08:54
Оценка:
Здравствуйте, mDmitriy, Вы писали:

D>Можно ли написать как-то покрасивее?

А покрасивее — это как? Что смущает?
Re[2]: Как правильно вызвать последовательность задач?
От: mDmitriy Россия  
Дата: 13.09.17 09:13
Оценка:
Здравствуйте, Nikolay_Ch, Вы писали:
D>>Можно ли написать как-то покрасивее?
N_C>А покрасивее — это как? Что смущает?
в 1 оператор
и не стартовать задачи из массива руками
в примерах вроде можно стартовать 1 задачу, остальные как-то подтягиваются
а у меня так не получается
Re[2]: Как правильно вызвать последовательность задач?
От: mDmitriy Россия  
Дата: 13.09.17 09:18
Оценка:
Здравствуйте, _Raz_, Вы писали:
_R_>
_R_>  await first();
_R_>  Parallel.Invoke(
_R_>    () => {},
_R_>    () => {},
_R_>    () => {},
_R_>  );

зачем await перед first()?
и мне нужно чтобы в Task все было
Re[2]: Как правильно вызвать последовательность задач?
От: _Raz_  
Дата: 13.09.17 09:18
Оценка:
    var task = Task.Run(() => {
        first();
        Parallel.Invoke(
        ...
        );
    });
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
Re[3]: Как правильно вызвать последовательность задач?
От: Nikolay_Ch Россия  
Дата: 13.09.17 09:19
Оценка:
Здравствуйте, mDmitriy, Вы писали:

D>в 1 оператор

В один оператор — это все равно будет набор операторов, умещенных в одну строку (см. мой пример)

D>в примерах вроде можно стартовать 1 задачу, остальные как-то подтягиваются

В каких примерах? Покажите. Что значит "как-то"? Примеры надо разбирать, чтобы понимать это "как-то"
Re: Как правильно вызвать последовательность задач?
От: _Raz_  
Дата: 13.09.17 09:34
Оценка:
Здравствуйте, mDmitriy, Вы писали:

Еще вариант

    var afters =
    {
        new Task(after1, TaskCreationOptions.AttachedToParent),
        new Task(after2, TaskCreationOptions.AttachedToParent),
        ...
        new Task(afterN, TaskCreationOptions.AttachedToParent)
    }

    Task.Run(() =>
    {
        first();
        afters.ForEach(a => a.Start());
    })
    .Wait();
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
Re: Как правильно вызвать последовательность задач?
От: StatujaLeha на правах ИМХО
Дата: 13.09.17 10:05
Оценка:
Здравствуйте, mDmitriy, Вы писали:

D>Все привет!


D>При старте приложения надо запустить фоном выполнение нескольких тяжеловесных методов

            var first = new Action(() =>
                                   {
                                       Console.WriteLine("First!");
                                       Thread.Sleep(200);
                                   });
            var after1 = new Action(() => { Thread.Sleep(30); Console.WriteLine("1"); });
            var after2 = new Action(() => { Thread.Sleep(2000); Console.WriteLine("2"); });
            var after3 = new Action(() => { Thread.Sleep(10); Console.WriteLine("3"); });

            Task.Run(async () =>
                     {
                         first();
                         await Task.WhenAll(Task.Run(after1), Task.Run(after2), Task.Run(after3));
                     }).Wait();
Re: Как правильно вызвать последовательность задач?
От: karbofos42 Россия  
Дата: 13.09.17 12:16
Оценка:
Здравствуйте, mDmitriy, Вы писали:

D>Все привет!


D>При старте приложения надо запустить фоном выполнение нескольких тяжеловесных методов

D>Имеем:
D>
D>var first = new Action(() => {});
D>var after1 = new Action(() => {});
D>var after2 = new Action(() => {});
D>...
D>var afterN = new Action(() => {});
D>

D>Нужно дождаться выполнения метода first и запустить параллельно все остальные
D>Сейчас это работает так:
D>
D>var _afters = 
D>{
D>   new Task(after1),
D>   new Task(after2),
D>   ...
D>   new Task(afterN),
D>}

D>var task = Task.Run(() => first).ContinueWith(t =>
D>                {
D>                    _afters.ForEach(a => a.Start());
D>                    Task.WaitAll(_afters);
D>                });
D>

D>Можно ли написать как-то покрасивее?
D>Спасибо...

Вместо _afters завести ActionBlock?
Re[2]: Как правильно вызвать последовательность задач?
От: _Raz_  
Дата: 13.09.17 12:28
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>Вместо _afters завести ActionBlock?


Разные же анонимные методы для задач, а ActionBlock работает только с одним. Да и ActionBlock переходит в ошибку после первого эксепшина и не выполняет оставшуюся очередь — подойдет ли это топик стартеру.
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
Re[2]: Как правильно вызвать последовательность задач?
От: mDmitriy Россия  
Дата: 13.09.17 12:33
Оценка:
Здравствуйте, karbofos42, Вы писали:
K>Вместо _afters завести ActionBlock?
Спасибо, подумаю в его сторону
Re[3]: Так подойдет, спасибо!
От: mDmitriy Россия  
Дата: 13.09.17 12:37
Оценка:
Здравствуйте, Nikolay_Ch, Вы писали:
N_C>
var _afters = new[] { after1, after2, after3, after4, after5 };
Task.Run(()=>first).ContinueWith((t)=>Parallel.Invoke(_afters));
Re[3]: Как правильно вызвать последовательность задач?
От: karbofos42 Россия  
Дата: 13.09.17 13:04
Оценка:
Здравствуйте, _Raz_, Вы писали:

_R_>Здравствуйте, karbofos42, Вы писали:


K>>Вместо _afters завести ActionBlock?


_R_>Разные же анонимные методы для задач, а ActionBlock работает только с одним. Да и ActionBlock переходит в ошибку после первого эксепшина и не выполняет оставшуюся очередь — подойдет ли это топик стартеру.


Ну, какую-нибудь такую штуку можно написать: ActionBlock<Action>((a) => a.Invoke()). Но для этого конечно Parallel.Invoke логичнее использовать.
Re[4]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 14.09.17 09:39
Оценка:
Здравствуйте, mDmitriy, Вы писали:

D>var _afters = new[] { after1, after2, after3, after4, after5 };

D>Task.Run(()=>first).ContinueWith((t)=>Parallel.Invoke(_afters));[/cs]

Как я понял по описанию Parallel.Invoke, получится, что ContinueWith запускает Parallel.Invoke и ждет, пока он отработает(т.е. таска ContinueWith будет периодически получать время на выполнение, даже если не все задачи завершены).
Если же сделать как-нибудь через await
Task.Run(() => first()).ContinueWith(async (_) => await Task.WhenAll(Task.Run(after1), Task.Run(after2), Task.Run(after3)))

то таска ContinueWith запустит все задачи и в следующий раз будет разбужена только по завершении всех задач.
Re[5]: Так подойдет, спасибо!
От: Nikolay_Ch Россия  
Дата: 14.09.17 11:53
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

SL>то таска ContinueWith запустит все задачи и в следующий раз будет разбужена только по завершении всех задач.

Э... Что? Первая таска завершится и после нее начнет выполнятся вторая таска. Вторая будет в состоянии ожидания, пока Parallel не завершится.
По-моему разницы быть не должно.
Re[6]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 14.09.17 12:26
Оценка:
Здравствуйте, 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?
Re[7]: Так подойдет, спасибо!
От: Nikolay_Ch Россия  
Дата: 14.09.17 13:38
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

SL>И как тредпул теперь поймет, что до завершения всех тасков after не надо тратить вычислительные ресурсы на таску, из которой запущен Parallel.Invoke?

Посмотрите в исходники.Net... Там есть несколько вариантов работы Invoke, в зависимости от количества переданных Action'ов... Один из которых WaitAll, другой — FastWaitAll...
Отредактировано 14.09.2017 13:39 Nikolay_Ch . Предыдущая версия . Еще …
Отредактировано 14.09.2017 13:39 Nikolay_Ch . Предыдущая версия .
Отредактировано 14.09.2017 13:38 Nikolay_Ch . Предыдущая версия .
Re[7]: Так подойдет, спасибо!
От: _Raz_  
Дата: 14.09.17 13:58
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

SL>2. Ставим на паузу таску ContinueWith.


Это как?

SL>4. Идем обратно в таску ContinueWith и завершаем ее.


Откуда идем-то?

SL>Т.е. мы тратим на таску ContinueWith ресурсы только тогда, когда оно реально необходимо.


В рассматриваем примере этот таск завершится сразу после вызова WhenAll, то есть ресурсов на нее не будет затрачено совсем. Ресурсы будут использованы в таске, который создаст метод WhenAll.

SL>В примере через await оно так и должно работать.


Это потому что контекст захватили, а теперь добавь .ConfigureAwait(false) и посмотри что будет с таской ContinueWith.

SL>Пришли мы к вызову Parallel.Invoke, запустили все таски after.


Parallel.Invoke сам создает и запускает таски. Ему передаются экшены.

SL>И как тредпул теперь поймет, что до завершения всех тасков after не надо тратить вычислительные ресурсы на таску, из которой запущен Parallel.Invoke?


Почему не надо то, если там работает Parallel.Invoke.
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
Re[8]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 14.09.17 14:47
Оценка:
Здравствуйте, Nikolay_Ch, Вы писали:

N_C>Здравствуйте, StatujaLeha, Вы писали:


SL>>И как тредпул теперь поймет, что до завершения всех тасков after не надо тратить вычислительные ресурсы на таску, из которой запущен Parallel.Invoke?

N_C>Посмотрите в исходники.Net... Там есть несколько вариантов работы Invoke, в зависимости от количества переданных Action'ов... Один из которых WaitAll, другой — FastWaitAll...

Спасибо.
Т.е. там во всех ветках какой-либо Wait на другие таски.
Ждем на ManualResetEventSlim.

Тут мне и непонятно: если у меня есть Task и внутри него вызывается какой-то Task.Wait*, то как будет работать тредпул с этой таской?

Допустим, у нас первая таска завершается быстро, а остальные работают большее время.

В случае, ContinueWith(async (_) => await Task.WhenAll(...)) все равно будет один вход в таску с await и один выход из нее.
Я подозреваю, что в случае ContinueWith(() => Parallel.Invoke(...)) тред пул будет периодически давать время таске с Invoke и она будет просто тратить время на ожидание завершения остальных тасков, не выполняя полезной работы.
Re[9]: Так подойдет, спасибо!
От: Nikolay_Ch Россия  
Дата: 14.09.17 15:04
Оценка:
SL>В случае, ContinueWith(async (_) => await Task.WhenAll(...)) все равно будет один вход в таску с await и один выход из нее.
SL>Я подозреваю, что в случае ContinueWith(() => Parallel.Invoke(...)) тред пул будет периодически давать время таске с Invoke и она будет просто тратить время на ожидание завершения остальных тасков, не выполняя полезной работы.
Ну так посмотрите в исходниках в чем отличие WhenAll от WaitAll и FastWaitAll
Думаю, что Вы удивитесь (а может и нет — смотря с какой стороны посмотреть)
Re[8]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 14.09.17 15:10
Оценка:
Здравствуйте, _Raz_, Вы писали:

SL>>2. Ставим на паузу таску ContinueWith.

_R_>Это как?

Через await. Тред пул не будет передавать таску потоку из пула, пока не завершится таска под await-ом.

SL>>4. Идем обратно в таску ContinueWith и завершаем ее.

_R_>Откуда идем-то?

Тредпул мониторит, что завершилась таска под await-ом и это сигнал, что можно продолжить таску, которая содержит этот await.

SL>>Т.е. мы тратим на таску ContinueWith ресурсы только тогда, когда оно реально необходимо.

_R_>В рассматриваем примере этот таск завершится сразу после вызова WhenAll, то есть ресурсов на нее не будет затрачено совсем. Ресурсы будут использованы в таске, который создаст метод WhenAll.

Вот именно. А в случае Parallel.Invoke как будет? Я посмотрел исходники.
Как я понял, мы придем из первой строчки во вторую:
https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Parallel.cs,215
https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs,5180

Сценарий: первая таска из after выполняется очень быстро, оставшиеся медленно.
Получится, что Parallel.Invoke будет тратить ресурсы на то, чтобы периодически чекать, завершились ли задачи из after.
А этого можно избежать.

SL>>И как тредпул теперь поймет, что до завершения всех тасков after не надо тратить вычислительные ресурсы на таску, из которой запущен Parallel.Invoke?

_R_>Почему не надо то, если там работает Parallel.Invoke.

А смысл?
Туда нужно вернуться один раз, когда все задачи завершены.
В примере через await так и произойдет.
Re[9]: Так подойдет, спасибо!
От: _Raz_  
Дата: 14.09.17 16:44
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

SL>Сценарий: первая таска из after выполняется очень быстро, оставшиеся медленно.

SL>Получится, что Parallel.Invoke будет тратить ресурсы на то, чтобы периодически чекать, завершились ли задачи из after.

Это откуда такое получается? В Parallel.Invoke нет никакого периодического чеканья.

SL>А смысл?


Не забывай, что в Parallel.Invoke передаются экшены и фабрика тасков для этих экшенов должна где-то выполняться.

SL>Туда нужно вернуться один раз, когда все задачи завершены.


А Parallel.Invoke никуда и не уходил, а это менее затратно по ресурсам

SL>В примере через await так и произойдет.


А дальше что? А дальше сразу конец метода. Вот и получилось, что держали-держали поток и сразу вышли Зачем держали
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
Re[10]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 14.09.17 20:05
Оценка:
Здравствуйте, _Raz_, Вы писали:

_R_>Это откуда такое получается? В Parallel.Invoke нет никакого периодического чеканья.


Есть. Если чекнуть вторую ссылку на исходники фреймворка, которую я дал в сообщении ранее, то там будет функция WaitAllBlockingCore.
Parallel.Invoke может по разному запустить переданные ему Action-ы, но в конце всегда будет какой-либо Wait.
Изучив Wait-ы, можно понять, что ожидание будет выполняться через ManualResetEventSlim.
https://msdn.microsoft.com/en-us/library/system.threading.manualreseteventslim(v=vs.110).aspx

ManualResetEventSlim uses busy spinning for a short time while it waits for the event to become signaled.


_R_>Не забывай, что в Parallel.Invoke передаются экшены и фабрика тасков для этих экшенов должна где-то выполняться.


Так и в чем проблема?
Например, если экшенов относительно мало, то все выполняется следующим кодом из потока, запустившего Invoke
                    // Launch all actions as tasks
                    for (int i = 1; i < tasks.Length; i++)
                    {
                        tasks[i] = Task.Factory.StartNew(actionsCopy[i], parallelOptions.CancellationToken, TaskCreationOptions.None,
                                                            InternalTaskOptions.None, parallelOptions.EffectiveTaskScheduler);
                    }


_R_>А Parallel.Invoke никуда и не уходил, а это менее затратно по ресурсам


Как бы в этом и нюанс, что в некоторых сценариях таска с Parallel.Invoke будет кушать вычислительные ресурсы, не направленные на выполнение задач after.
Так что это точно не менее затратно по ресурсам.

_R_>А дальше что? А дальше сразу конец метода. Вот и получилось, что держали-держали поток и сразу вышли Зачем держали


Потоками тредпул рулит. А не таски.
И выделенное сообщение: суть await-а в том, что при его достижении тредпула отберет поток у задачи и не будет назначать до тех пор, пока таска под await-ом не завершится.
Re[11]: Так подойдет, спасибо!
От: Nikolay_Ch Россия  
Дата: 14.09.17 20:23
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

SL>Как бы в этом и нюанс, что в некоторых сценариях таска с Parallel.Invoke будет кушать вычислительные ресурсы, не направленные на выполнение задач after.

Погодите-ка... Но WhenAll работает так же, как и Parallell.Invoke. Где будет экономия?
Re[10]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 14.09.17 20:28
Оценка:
Здравствуйте, Nikolay_Ch, Вы писали:

N_C>Ну так посмотрите в исходниках в чем отличие WhenAll от WaitAll и FastWaitAll

N_C>Думаю, что Вы удивитесь (а может и нет — смотря с какой стороны посмотреть)

Да, посмотрел.
WhenAll сам по себе не делает busy waiting, а WaitAll и FastWaitAll делают.
Выходит, что я убираю один busy waiting, если делаю через await.
Или я что-то не учел?
Re[12]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 14.09.17 20:34
Оценка:
Здравствуйте, Nikolay_Ch, Вы писали:

N_C>Погодите-ка... Но WhenAll работает так же, как и Parallell.Invoke. Где будет экономия?


Не похоже.
https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs,6016
https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs,6089

Чекните. Там по завершении всех задач тупо флажок какой-то выставляется в Invoke, а busy waiting-а нет.
Re[11]: Так подойдет, спасибо!
От: Nikolay_Ch Россия  
Дата: 14.09.17 20:44
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

SL>WhenAll сам по себе не делает busy waiting, а WaitAll и FastWaitAll делают.

Не делает, но (судя по исходникам) и параллельно задачи не запускает, т.е. выполняет их последовательно одну за одной...
Re[11]: Так подойдет, спасибо!
От: _Raz_  
Дата: 14.09.17 20:45
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

SL>Есть. Если чекнуть вторую ссылку на исходники фреймворка, которую я дал в сообщении ранее, то там будет функция WaitAllBlockingCore.

SL>Parallel.Invoke может по разному запустить переданные ему Action-ы, но в конце всегда будет какой-либо Wait.
SL>Изучив Wait-ы, можно понять, что ожидание будет выполняться через ManualResetEventSlim.
SL>https://msdn.microsoft.com/en-us/library/system.threading.manualreseteventslim(v=vs.110).aspx
SL>

SL>ManualResetEventSlim uses busy spinning for a short time while it waits for the event to become signaled.


Про чеканье стало понятно. Теперь возник вопрос в чем разница Parallel.Invoke и Task.WaitAll в разрезе этого чеканья.

_R_>>Не забывай, что в Parallel.Invoke передаются экшены и фабрика тасков для этих экшенов должна где-то выполняться.

SL>Так и в чем проблема?

Так и нет проблемы. Это ответ на "А смысл? Туда нужно вернуться один раз, когда все задачи завершены.".

SL>Например, если экшенов относительно мало, то все выполняется следующим кодом из потока, запустившего Invoke


Если ты видишь и понимаешь этот код, то смысл чего тебе не понятен?

SL>Как бы в этом и нюанс, что в некоторых сценариях таска с Parallel.Invoke будет кушать вычислительные ресурсы, не направленные на выполнение задач after.


А что так загадочно? Рассказывай про сценарии и озвучь список ресурсов.

SL>Так что это точно не менее затратно по ресурсам.


Это "точно" учитывает все if-ы внутри Parallel.Invoke и учитывает отсутствие переключение контекстов и дороговизну создания новых потоков (это про MaxDegreeOfParallelism)?

_R_>>А дальше что? А дальше сразу конец метода. Вот и получилось, что держали-держали поток и сразу вышли Зачем держали

SL>Потоками тредпул рулит. А не таски.

И что? Поток то все равно есть и он занимает ресурсы (не направленные на выполнение задач after ).

SL>И выделенное сообщение: суть await-а в том, что при его достижении тредпула отберет поток у задачи и не будет назначать до тех пор, пока таска под await-ом не завершится.


Суть await-а в синтаксическом сахаре. Если переписать на продолжениях суть изменится или нет?

И можно про то как тредпул отбирает поток у задачи?
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
Re[13]: Так подойдет, спасибо!
От: Nikolay_Ch Россия  
Дата: 14.09.17 20:58
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

N_C>>Не делает, но (судя по исходникам) и параллельно задачи не запускает, т.е. выполняет их последовательно одну за одной...

SL>Он их вообще не запускает.
Согласен, недосмотрел.

SL>Поэтому в моем примере туда передаются задачи из Task.Run, т.е. уже запущенные(это обеспечит параллельность).

SL>
SL>Task.WhenAll(Task.Run(after1), Task.Run(after2), Task.Run(after3))
SL>

Ну, тогда у меня последний аргумент — Parallel может лучше суметь распараллелить таски, чем последовательный их запуск...
Re[12]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 14.09.17 21:14
Оценка:
Здравствуйте, _Raz_, Вы писали:

_R_>Про чеканье стало понятно. Теперь возник вопрос в чем разница Parallel.Invoke и Task.WaitAll в разрезе этого чеканья.


Ок.
Между Parallel.Invoke и Task.WaitAll нет разницы.
А между Parallel.Invoke и Task.When All она есть.

_R_>Так и нет проблемы. Это ответ на "А смысл? Туда нужно вернуться один раз, когда все задачи завершены.".


Так и я думаю, что проблемы нет. Просто я не понял, к чему замечание "Не забывай, что в Parallel.Invoke передаются экшены и фабрика тасков для этих экшенов должна где-то выполняться."?
Это же ни на что не влияет.

_R_>Если ты видишь и понимаешь этот код, то смысл чего тебе не понятен?


Мне как раз все понятно

_R_>А что так загадочно? Рассказывай про сценарии и озвучь список ресурсов.


Я его уже озвучивал тебе: https://rsdn.org/forum/dotnet/6904266.1
Автор: StatujaLeha
Дата: 14.09.17


_R_>Это "точно" учитывает все if-ы внутри Parallel.Invoke и учитывает отсутствие переключение контекстов и дороговизну создания новых потоков (это про MaxDegreeOfParallelism)?


Ты о чем? В примере топикстартера Parallel.Invoke точно так же скидывает таски в тред пул, в котором все потоки уже созданы.
Таски в обоих вариантах запускаются идентично.

_R_>И что? Поток то все равно есть и он занимает ресурсы (не направленные на выполнение задач after ).


Это не так. Видимо, надо изучить матчасть.

_R_>Суть await-а в синтаксическом сахаре. Если переписать на продолжениях суть изменится или нет?

_R_>И можно про то как тредпул отбирает поток у задачи?

Ясно
Рекомендую изучить матчать: async/await вообще-то заставляют компилятор трансформировать функцию.
Google в помощь: "async await state machine".
Не то чтобы чтиво большое, но и не пару строк.
Re[14]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 14.09.17 21:19
Оценка:
Здравствуйте, Nikolay_Ch, Вы писали:

N_C>Ну, тогда у меня последний аргумент — Parallel может лучше суметь распараллелить таски, чем последовательный их запуск...


В смысле?
При дефолтных аргументах(как у автора) что в моем примере, что внутри у Parallel.Invoke таски будут идентично запущены.

PS Task.Run() не дожидается окончания работы таски, которую он создал.
Re[13]: Так подойдет, спасибо!
От: _Raz_  
Дата: 14.09.17 22:51
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

SL>Ок.

SL>Между Parallel.Invoke и Task.WaitAll нет разницы.
SL>А между Parallel.Invoke и Task.When All она есть.

Ок.

SL>Так и я думаю, что проблемы нет. Просто я не понял, к чему замечание "Не забывай, что в Parallel.Invoke передаются экшены и фабрика тасков для этих экшенов должна где-то выполняться."?

SL>Это же ни на что не влияет.

Это влияет на то, почему Parallel.Invoke работает в потоке ContinueWith — в этом же твое изначальное замечание
Автор: StatujaLeha
Дата: 14.09.17
было. А теперь, оказывается, что ни на что не влияет

_R_>>А что так загадочно? Рассказывай про сценарии и озвучь список ресурсов.

SL>Я его уже озвучивал тебе: https://rsdn.org/forum/dotnet/6904266.1
Автор: StatujaLeha
Дата: 14.09.17


Это вот этот: "Сценарий: первая таска из after выполняется очень быстро, оставшиеся медленно."?
И из него ты делаешь вывод: "Как бы в этом и нюанс, что в некоторых сценариях таска с Parallel.Invoke будет кушать вычислительные ресурсы, не направленные на выполнение задач after."?

SL>Ты о чем?


Я о категоричности "это точно не менее затратно по ресурсам".

SL>В примере топикстартера Parallel.Invoke точно так же скидывает таски в тред пул, в котором все потоки уже созданы.

SL>Таски в обоих вариантах запускаются идентично.

Значит ты смотрел исходники Parallel.Invoke, сказал, что понял их, и все равно настаиваешь на категоричном "идентично"?

_R_>>И что? Поток то все равно есть и он занимает ресурсы (не направленные на выполнение задач after ).

SL>Это не так. Видимо, надо изучить матчасть.

Значит, все-таки настаиваешь, что "тредпул отберет поток"?

SL>Ясно

SL>Рекомендую изучить матчать: async/await вообще-то заставляют компилятор трансформировать функцию.
SL>Google в помощь: "async await state machine".
SL>Не то чтобы чтиво большое, но и не пару строк.

Воспользовался твоими рекомендациями, но подтверждения для "суть await-а в том, что при его достижении тредпула отберет поток у задачи и не будет назначать до тех пор, пока таска под await-ом не завершится" не нашел. Так что позволю себе повторить вопросы:

Если await переписать на продолжениях суть изменится или нет?
И можно про то как тредпул отбирает поток у задачи?
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
Re[15]: Так подойдет, спасибо!
От: Nikolay_Ch Россия  
Дата: 14.09.17 23:06
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

SL>Здравствуйте, Nikolay_Ch, Вы писали:

SL>В смысле?
SL>При дефолтных аргументах(как у автора) что в моем примере, что внутри у Parallel.Invoke таски будут идентично запущены.
Вот из документации:

// In the algorithm below, if the number of actions is greater than this, we automatically
// use Parallel.For() to handle the actions, rather than the Task-per-Action strategy.

В общем, все Экшны стартуют как Таски только для количества меньше 10...
Re[16]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 15.09.17 16:41
Оценка:
Здравствуйте, Nikolay_Ch, Вы писали:

N_C>Вот из документации:

N_C>

N_C>// In the algorithm below, if the number of actions is greater than this, we automatically
N_C>// use Parallel.For() to handle the actions, rather than the Task-per-Action strategy.

N_C>В общем, все Экшны стартуют как Таски только для количества меньше 10...

https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Parallel.cs,318
Все равно это все придет к Wait.
Re[14]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 15.09.17 19:16
Оценка:
Здравствуйте, _Raz_, Вы писали:

_R_>Это влияет на то, почему Parallel.Invoke работает в потоке ContinueWith — в этом же твое изначальное замечание
Автор: StatujaLeha
Дата: 14.09.17
было. А теперь, оказывается, что ни на что не влияет


Чего?
Мое изначальное замечание действительно в этом сообщении. Как мне кажется, оно ясно сформулировано

Как я понял по описанию Parallel.Invoke, получится, что ContinueWith запускает Parallel.Invoke и ждет, пока он отработает(т.е. таска ContinueWith будет периодически получать время на выполнение, даже если не все задачи завершены).


И мой вариант убирает это ожидание.

_R_>>>А что так загадочно? Рассказывай про сценарии и озвучь список ресурсов.

SL>>Я его уже озвучивал тебе: https://rsdn.org/forum/dotnet/6904266.1
Автор: StatujaLeha
Дата: 14.09.17


_R_>Это вот этот: "Сценарий: первая таска из after выполняется очень быстро, оставшиеся медленно."?

_R_>И из него ты делаешь вывод: "Как бы в этом и нюанс, что в некоторых сценариях таска с Parallel.Invoke будет кушать вычислительные ресурсы, не направленные на выполнение задач after."?

Да, я так думаю. Если первая таска выполнится быстро, то пойдет ожидание на ManualResetEventSlim, busy waiting.

SL>>Ты о чем?

_R_>Я о категоричности "это точно не менее затратно по ресурсам".

Ну ок. У меня пока замеров нету, так что снимаю это утверждение.
Тогда попрошу как-то подкрепить утверждение отсюда: http://rsdn.org/forum/dotnet/6904317.1
Автор: _Raz_
Дата: 14.09.17

А Parallel.Invoke никуда и не уходил, а это менее затратно по ресурсам


Как бы выходит, что в приведенном мной сценарии Parallel.Invoke действительно никуда не уходил и кушал ресурсы на ManualResetEventSlim.
Почему же это считается менее затратным?

_R_>Значит ты смотрел исходники Parallel.Invoke, сказал, что понял их, и все равно настаиваешь на категоричном "идентично"?


Согласен, слово "идентично" не подходит.
Если нет возражений, то заменю на "схожим образом".
Мой запуск
await Task.WhenAll(Task.Run(after1), Task.Run(after2), Task.Run(after3))


Запуск в Parallel.Invoke, https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Parallel.cs,362
                    // Launch all actions as tasks
                    for (int i = 1; i < tasks.Length; i++)
                    {
                        tasks[i] = Task.Factory.StartNew(actionsCopy[i], parallelOptions.CancellationToken, TaskCreationOptions.None,
                                                            InternalTaskOptions.None, parallelOptions.EffectiveTaskScheduler);
                    }
 
                    // Optimization: Use current thread to run something before we block waiting for all tasks.
                    tasks[0] = new Task(actionsCopy[0]);
                    tasks[0].RunSynchronously(parallelOptions.EffectiveTaskScheduler);

Разница в выделенном.

_R_>Значит, все-таки настаиваешь, что "тредпул отберет поток"?


https://www.codeproject.com/Articles/535635/Async-Await-and-the-Generated-StateMachine
Можешь сам убедиться: в состояниях State Machine, соответствующих await-ам, делается запуск операции под await-ом и дальше выход из функции MoveNext.
После этого поток свободен.

_R_>Воспользовался твоими рекомендациями, но подтверждения для "суть await-а в том, что при его достижении тредпула отберет поток у задачи и не будет назначать до тех пор, пока таска под await-ом не завершится" не нашел. Так что позволю себе повторить вопросы:


Ок
Как объяснишь результаты работы кода ниже?
Особенно выделенной части, когда исходный Action до await-а обрабатывается тредом 4, после await-а тредом 3, а Continue снова тредом 4.
            for (int i = 0; i < 5; i++)
            {
                Task.Run(async () =>
                         {
                             Console.WriteLine($"Thread before: {Thread.CurrentThread.ManagedThreadId}");
                             await Task.Delay(10);
                             Console.WriteLine($"Thread after: {Thread.CurrentThread.ManagedThreadId}");

                             Thread.SpinWait(1000);
                         })
                    .ContinueWith((_) => Console.WriteLine($"Continue thread: {Thread.CurrentThread.ManagedThreadId}"))
                    .Wait();
                Console.WriteLine();
            }

Thread before: 3
Thread after: 4
Continue thread: 4

Thread before: 4
Thread after: 6
Continue thread: 6

Thread before: 3
Thread after: 4
Continue thread: 4

Thread before: 6
Thread after: 3
Continue thread: 3

Thread before: 4
Thread after: 3
Continue thread: 4


_R_>Если await переписать на продолжениях суть изменится или нет?


Кинь плз пример кода, как ты предлагаешь это сделать.

_R_>И можно про то как тредпул отбирает поток у задачи?


Я механику в деталях не знаю, но выше привел пример, где зафиксировано такое поведение + ссылку на декомпилированную state machine, в которой тоже видно, что после await-а поток освобождается.
Re[15]: Так подойдет, спасибо!
От: _Raz_  
Дата: 15.09.17 20:54
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

SL>Чего?


Того

SL>Мое изначальное замечание действительно в этом сообщении. Как мне кажется, оно ясно сформулировано

SL>

SL>Как я понял по описанию Parallel.Invoke, получится, что ContinueWith запускает Parallel.Invoke и ждет, пока он отработает(т.е. таска ContinueWith будет периодически получать время на выполнение, даже если не все задачи завершены).


А я тебе на это отвечаю — "Не забывай, что в Parallel.Invoke передаются экшены и фабрика тасков для этих экшенов должна где-то выполняться."
То есть он не ждет, а выполняет полезную работу. Так понятней, надеюсь

SL>И мой вариант убирает это ожидание.


Я отвечал на то что до скобок.

SL>Да, я так думаю. Если первая таска выполнится быстро, то пойдет ожидание на ManualResetEventSlim, busy waiting.


Так оно в любом случае будет. Не обязательно busy, но будет.

SL>Как бы выходит, что в приведенном мной сценарии Parallel.Invoke действительно никуда не уходил и кушал ресурсы на ManualResetEventSlim.

SL>Почему же это считается менее затратным?

Ты там смеющийся смайлик не заметил?

SL>Мой запуск

SL>Запуск в Parallel.Invoke, https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Parallel.cs,362
SL>Разница в выделенном.

И в выделенном, и до выделенного, и после выделенного. Я все пытаюсь тебя подтолкнуть, что Parallel.Invoke это чуть больше запуска потоков — там и некоторая оптимизация и сбор ошибок.

SL>Можешь сам убедиться: в состояниях State Machine, соответствующих await-ам, делается запуск операции под await-ом и дальше выход из функции MoveNext.


Я спрашивал про тредпул. Как называется его метод отбирающий поток?

SL>Как объяснишь результаты работы кода ниже?

SL>Особенно выделенной части, когда исходный Action до await-а обрабатывается тредом 4, после await-а тредом 3, а Continue снова тредом 4.

Хватит уже щеки надувать. Ты меня не собеседуешь.

SL>Кинь плз пример кода, как ты предлагаешь это сделать.


    for (var i = 0; i < 5; i++)
    {
        Task.Factory.StartNew(() =>
            {
                Console.WriteLine($"Thread before: {Thread.CurrentThread.ManagedThreadId}");
                Task.Delay(10)
                    .ContinueWith(t =>
                    {
                        Console.WriteLine($"Thread after: {Thread.CurrentThread.ManagedThreadId}");
                        Thread.SpinWait(1000);
                    }, TaskContinuationOptions.AttachedToParent);
            })
            .ContinueWith(_ => Console.WriteLine($"Continue thread: {Thread.CurrentThread.ManagedThreadId}"))
            .Wait();
        Console.WriteLine();
    }


SL>Я механику в деталях не знаю


Вот сейчас было ваще на отличненько

SL> выше привел пример, где зафиксировано такое поведение + ссылку на декомпилированную state machine, в которой тоже видно, что после await-а поток освобождается.


Значит даю направление: тредпул во всей этой истории не играет ни малейшей роли и ничего ни у кого не отбирает. Так же как и await — да, да, он все еще синтаксический сахар и не важно во что он там разворачивается (кстати, ты и тут ошибаешься: разворачивается async, а не await). А играют тут шедулер и контекст выполнения.
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
Re[16]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 16.09.17 22:10
Оценка:
Здравствуйте, _Raz_, Вы писали:

_R_>То есть он не ждет, а выполняет полезную работу. Так понятней, надеюсь


_R_>Я отвечал на то что до скобок.


Полезная работа Parallel.Invoke в целом такая же, как и полезная работа Task.WhenAll.
А вот busy waiting, который может произойти в Parallel.Invoke, можно избежать.

_R_>Так оно в любом случае будет. Не обязательно busy, но будет.


Разница в том, что на этот busy waiting из Parallel.Invoke будут тратится ресурсы потока из тред пула.
Хотя их можно потратить на другую работу.

_R_>Ты там смеющийся смайлик не заметил?


Ах, смайлик!

_R_>И в выделенном, и до выделенного, и после выделенного. Я все пытаюсь тебя подтолкнуть, что Parallel.Invoke это чуть больше запуска потоков — там и некоторая оптимизация и сбор ошибок.


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

_R_>Я спрашивал про тредпул. Как называется его метод отбирающий поток?


Ок, признаю: тред пул не отбирает поток.
Поток тредпула, выделенный на задачу, сам туда возвращается
Как все поменялось!

В свою очередь, хочу напомнить, как мы пришли к этому вопросу.
Ты написал http://rsdn.org/forum/dotnet/6904317.1:
Автор: _Raz_
Дата: 14.09.17

Вот и получилось, что держали-держали поток и сразу вышли

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

Комментарии будут?

_R_>Хватит уже щеки надувать. Ты меня не собеседуешь.


Ой все?
Как-то так выходит, что ты говорил одно, а работает оно иначе
Не смущает?

_R_>
...
_R_>


Авторского примера плз, его же обсуждаем.

_R_>Вот сейчас было ваще на отличненько


Да ладно. Не сравнится, с твоим "хватит щеки надувать" вместо ответа по существу :D

_R_>Значит даю направление: тредпул во всей этой истории не играет ни малейшей роли и ничего ни у кого не отбирает. Так же как и await — да, да, он все еще синтаксический сахар и не важно во что он там разворачивается


Ок, пусть async/await будет считать синтаксическим сахаром.
Но в свою очередь тоже даю тебе направление: иди учи матчасть.

_R_>(кстати, ты и тут ошибаешься: разворачивается async, а не await).


И не перевирай мои слова: я писал "async/await вообще-то заставляют компилятор трансформировать функцию".
А матчасть подучи. Тогда будешь понимать, что async — это флажок компилятору, что функцию надо трансформировать в State Machine, а количество состояний в этой State Machine зависит от количества await-ов.

_R_>А играют тут шедулер и контекст выполнения.


Вот ты постоянной что-то пишешь и ничем свои доводы не подкрепляешь.
А уже ведь было выяснено, что твои доводы бывают явно не верными.

Как бы буду рад, если кто-то покажет мне, в чем я заблуждаюсь/не прав.
Код так не тривиальный, может я что-то и упустил.
Но явно я не буду как-то всерьез воспринимать доводы от авторов, которые тупо в матчасти плавают
Re[17]: Так подойдет, спасибо!
От: _Raz_  
Дата: 17.09.17 01:40
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

SL>Полезная работа Parallel.Invoke в целом такая же, как и полезная работа Task.WhenAll.


Ты издеваешься?

SL>А вот busy waiting, который может произойти в Parallel.Invoke, можно избежать.

SL>Разница в том, что на этот busy waiting из Parallel.Invoke будут тратится ресурсы потока из тред пула.

Ты точно издеваешься. В первом предложении это предположение, а во втором уже утверждение.

SL>Хотя их можно потратить на другую работу.


Ну ты же понимаешь насколько это ерунда.

SL>Если можно, не подталкивай, а просто покажи


Ты же видел исходник Parallel.Invoke полностью и сказал, что понял его. Если ты его понял, то что тебе еще показать? Разницу между одной строкой и 197-ю строками?

SL>До сих пор ты только пишешь и ничем свои доводы не обосновываешь.

SL>При этом пример кода, когда твои слова явно не соответствуют действительности, уже был приведен.

Для меня очевидно, что ты мухлюешь и передергиваешь. И твои голословные обвинения идут лесом. И тот кусок был приведен тобой для подтверждения твоей же позиции — как тут я могу быть не прав? К тому-же позициции, которую ты поменял в двух последовательных сообщениях.

SL>Ок, признаю: тред пул не отбирает поток.

SL>Поток тредпула, выделенный на задачу, сам туда возвращается

Это же твоя базовая аргументация:

Потоками тредпул рулит. А не таски.
И выделенное сообщение: суть await-а в том, что при его достижении тредпула отберет поток у задачи и не будет назначать до тех пор, пока таска под await-ом не завершится.


Хотя, да — в главном то ты прав

SL>Как все поменялось!


По-твоему не значительно?

SL>В свою очередь, хочу напомнить, как мы пришли к этому вопросу.

SL>Ты написал http://rsdn.org/forum/dotnet/6904317.1:
Автор: _Raz_
Дата: 14.09.17

SL>

SL>Вот и получилось, что держали-держали поток и сразу вышли

SL>Хотя в предыдущем сообщении была ссылка на листинг, из которого явно видно, что поток нифига не держится таской.

В собственном глазу соринку не замечаешь? "и в следующий раз будет разбужена только по завершении всех задач.".

SL>Как-то так выходит, что ты говорил одно, а работает оно иначе

SL>Не смущает?

Не смеши меня.

SL>Авторского примера плз, его же обсуждаем.


В авторском коде нет ни одного await-а.

_R_>>(кстати, ты и тут ошибаешься: разворачивается async, а не await).

SL>И не перевирай мои слова: я писал "async/await вообще-то заставляют компилятор трансформировать функцию".

Я и не перевираю. И ниже ты сам подтверждаешь мои слова — await не заставляет трансформировать функцию.

SL>А матчасть подучи. Тогда будешь понимать, что async — это флажок компилятору, что функцию надо трансформировать в State Machine, а количество состояний в этой State Machine зависит от количества await-ов.


Оставь менторский тон для зеркала.

SL>Вот ты постоянной что-то пишешь и ничем свои доводы не подкрепляешь.

SL>А уже ведь было выяснено, что твои доводы бывают явно не верными.

Вот нравится мне твоя категоричность. Это юношеский максимализм, похоже.

SL>Как бы буду рад, если кто-то покажет мне, в чем я заблуждаюсь/не прав.

SL>Код так не тривиальный, может я что-то и упустил.

Ты главное упустил — никому не интересно сколько ресурсов занимает ожидание.
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
Re[18]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 18.09.17 21:55
Оценка:
Здравствуйте, _Raz_, Вы писали:

_R_>Ты издеваешься?


Так аргументируй, если не согласен.
Показал бы, где я не прав

_R_>Ты точно издеваешься. В первом предложении это предположение, а во втором уже утверждение.


Нет. Просто ты уже за отсутствием аргументов цепляешься к словам
А сценарий, где это busy waiting возникает, выше был приведен. Для него это утверждение справедливо.

_R_>Ну ты же понимаешь насколько это ерунда.


Если ты имеешь ввиду, что выигрыш от исключения busy waiting в приведенном мной сценарии мизерный, то, может и так.
У меня замеров нет, но допускаю, что мы говорим о каких-то процентах.

_R_>Ты же видел исходник Parallel.Invoke полностью и сказал, что понял его. Если ты его понял, то что тебе еще показать? Разницу между одной строкой и 197-ю строками?


Понимаешь, я посмотрел исходники Parallel.Invoke и там 198 строк. И это учитывая заглавие функции, комментарии, пустые строки, строки, где какая-нибудь фигня написана, типа одной скобки, логирование.
Строк, реализующих логику, в лучшем случае половина. Как видишь, строк только формально 198

А еще, я посмотрел исходники Task.WhenAll.
И ты удивишься, но там в сумме выходит 124 строки, при чем комментов и прочего барахла поменьше

Не удивлюсь, если при аккуратном подсчете содержательных строк выйдет, что кода примерно одинаково.

_R_>Для меня очевидно, что ты мухлюешь и передергиваешь.


Really?
А я думаю, что мухлеж и передергивание — это вот только что выше от тебя было, при сравнении размера кода Paralle.Invoke и Task.WhenAll
Ты при этом еще и выделил слово "полностью"

_R_>И твои голословные обвинения идут лесом.


Код, который явно работает не так, как ты писал, я не убирал и не подправлял

_R_>И тот кусок был приведен тобой для подтверждения твоей же позиции — как тут я могу быть не прав?


Ну и кто тут передергивает и мухлюет?
Ты не согласился с моим утверждением и сделал свое(ссылку на него я привел).
Я признал, что в моем утверждении есть неточности и поправил их.
И привел пример того, как твои слова полностью противоречат тому, как работает.

_R_>К тому-же позициции, которую ты поменял в двух последовательных сообщениях.


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

_R_>Это же твоя базовая аргументация:

_R_>

_R_>Потоками тредпул рулит. А не таски.
_R_>И выделенное сообщение: суть await-а в том, что при его достижении тредпула отберет поток у задачи и не будет назначать до тех пор, пока таска под await-ом не завершится.


_R_>Хотя, да — в главном то ты прав


Ну как базовая? Она была исходной, но я признал, что там есть неточности, и поправил свою позицию.
Я помню это, спасибо

SL>>Как все поменялось!


В контексте вопроса, из которого зародился этот спор, не поменялось ничего.

_R_>"и в следующий раз будет разбужена только по завершении всех задач.".


Это утверждение я пока не снимал
Если считаешь, что оно не справедливо, то вперед, буду рад, если опровергнешь

_R_>Не смеши меня.


Да это не смешно...

_R_>В авторском коде нет ни одного await-а.


Ок
Если про мой вариант, то тогда этого:
Task.Run(() => first()).ContinueWith(async (_) => await Task.WhenAll(Task.Run(after1), Task.Run(after2), Task.Run(after3))).Unwrap().Wait();


_R_>Я и не перевираю. И ниже ты сам подтверждаешь мои слова — await не заставляет трансформировать функцию.


Я вижу, что ты очень креативно повыдергивал слова из моего утверждения. У меня была пара async/await, ты оставил только async. И вуаля, "он не прав"!

_R_>Оставь менторский тон для зеркала.


Нет смысла, я и так постоянно что-то изучаю.

_R_>Вот нравится мне твоя категоричность. Это юношеский максимализм, похоже.


А, т.е. если тебя просят подкрепить свои слова чем-то, то это сразу юношеский максимализм?
Класс, чо.

_R_>Ты главное упустил — никому не интересно сколько ресурсов занимает ожидание.


Дак я согласен, что наша дискуссия может оказаться бесплодной. Какие-нибудь 1-2% по времени.

Ранее ты писал, что "играют тут шедулер и контекст выполнения".
Прояснишь ситуацию? Или "маэстро" не видит в этом необходимости?
Re[19]: Так подойдет, спасибо!
От: _Raz_  
Дата: 19.09.17 18:24
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

SL>Так аргументируй, если не согласен.

SL>Показал бы, где я не прав

Так ты выдвигаешь голословные утверждения. Я не собираюсь искать аргументы против категоричного и для меня очевидно ошибочного "Полезная работа Parallel.Invoke в целом такая же, как и полезная работа Task.WhenAll.".

_R_>>Ты точно издеваешься. В первом предложении это предположение, а во втором уже утверждение.

SL>Нет. Просто ты уже за отсутствием аргументов цепляешься к словам

Аргументируй, если не согласен.

_R_>>Ну ты же понимаешь насколько это ерунда.

SL>Если ты имеешь ввиду, что выигрыш от исключения busy waiting в приведенном мной сценарии мизерный, то, может и так.
SL>У меня замеров нет, но допускаю, что мы говорим о каких-то процентах.

Это не мы говорим, это ты говоришь.

SL>Понимаешь, я посмотрел исходники Parallel.Invoke и там 198 строк. И это учитывая заглавие функции, комментарии, пустые строки, строки, где какая-нибудь фигня написана, типа одной скобки, логирование.

SL>А еще, я посмотрел исходники Task.WhenAll.

Опять мухлюешь — здесь речь идет о сравнении с "await Task.WhenAll(Task.Run(after1), Task.Run(after2), Task.Run(after3))"

_R_>>Для меня очевидно, что ты мухлюешь и передергиваешь.

SL>Really?

Да. В каждом посте.

SL>А я думаю, что мухлеж и передергивание — это вот только что выше от тебя было, при сравнении размера кода Paralle.Invoke и Task.WhenAll

SL>Ты при этом еще и выделил слово "полностью"

Да, потому что без подтасовок сравнение было с одной строкой.

_R_>>И твои голословные обвинения идут лесом.

SL>Код, который явно работает не так, как ты писал, я не убирал и не подправлял

То что ты не убирал и не подправлял не является аргументом твоей правоты.

SL>Ну и кто тут передергивает и мухлюет?

SL>Ты не согласился с моим утверждением и сделал свое(ссылку на него я привел).
SL>Я признал, что в моем утверждении есть неточности и поправил их.
SL>И привел пример того, как твои слова полностью противоречат тому, как работает.

Понимаешь, все это — исключительно в твоей вселенной.

SL>В то же время, твоя позиция до сих пор как была некорректной, так и осталась.

SL>Просто ты этого не признаешь и все.

Просто ты не можешь сформулировать свои мысли. Все что я видел — это голословные обвинения.

SL>Ну как базовая? Она была исходной, но я признал, что там есть неточности, и поправил свою позицию.

SL>В контексте вопроса, из которого зародился этот спор, не поменялось ничего.

Это называется юлить.

_R_>>"и в следующий раз будет разбужена только по завершении всех задач.".

SL>Это утверждение я пока не снимал
SL>Если считаешь, что оно не справедливо, то вперед, буду рад, если опровергнешь

Не хочу идти на новую итерацию сего интереснейшего кхм... разговора.

_R_>>В авторском коде нет ни одного await-а.

SL>Если про мой вариант, то тогда этого:

Не-а. Не буду код писать. Догадаешься почему? Подсказка — дело не во мне.

SL>Я вижу, что ты очень креативно повыдергивал слова из моего утверждения. У меня была пара async/await, ты оставил только async. И вуаля, "он не прав"!


Именно так — только async. И, представь себе, что бы оставить только async — это слово надо выдернуть.

SL>Ранее ты писал, что "играют тут шедулер и контекст выполнения".

SL>Прояснишь ситуацию? Или "маэстро" не видит в этом необходимости?

Необходимости и раньше не было, а вот готовность поговорить об этом была. Но не в подобном русле.
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
Re[20]: Так подойдет, спасибо!
От: StatujaLeha на правах ИМХО
Дата: 20.09.17 20:27
Оценка:
Здравствуйте, _Raz_, Вы писали:

_R_>Так ты выдвигаешь голословные утверждения. Я не собираюсь искать аргументы против категоричного и для меня очевидно ошибочного "Полезная работа Parallel.Invoke в целом такая же, как и полезная работа Task.WhenAll.".


Настолько "очевидного", что даже не можешь в открытых листингах фреймворка показать, в чем же я не прав

_R_>Опять мухлюешь — здесь речь идет о сравнении с "await Task.WhenAll(Task.Run(after1), Task.Run(after2), Task.Run(after3))"


Ты просто мастер сравнений.
Есть код
await Task.WhenAll(Task.Run(after1), Task.Run(after2), Task.Run(after3))

а есть код
Parallel.Invoke(after1, after2, after3)


Любому первокласснику очевидно, что это в обоих примерах по одной строке кода.
Ну так казалось, до твоего "сравнения"...
Мы же не знали, что надо посмотреть, сколько строк занимает Parallel.Invoke, при этом не смотря на размер Task.WhenAll..
Только тогда станет очевидно, что второй пример в 198 раз больше!
Спасибо, что просвятил!

_R_>>>Для меня очевидно, что ты мухлюешь и передергиваешь.

SL>>Really?

_R_>Да. В каждом посте.


Ясно, понятно. Я не терапевт, дальше бессилен.
В дальнейшей беседе смысла не вижу: в мой адрес уже только и летят фразы "голословные обвинения", а вот с подкреплением делом этих слов пока движа нет
Свои аргументы я изложил, сообщения не редактировал, все на месте. Исходники фреймворка тоже открыты.
Если кому интересно, то проблем чекнуть справедливость моих слов нет. Ну или опровергнуть их
Удачи!
Re[21]: Так подойдет, спасибо!
От: _Raz_  
Дата: 20.09.17 21:46
Оценка:
Здравствуйте, StatujaLeha, Вы писали:

_R_>>Так ты выдвигаешь голословные утверждения. Я не собираюсь искать аргументы против категоричного и для меня очевидно ошибочного "Полезная работа Parallel.Invoke в целом такая же, как и полезная работа Task.WhenAll.".

SL>Настолько "очевидного", что даже не можешь в открытых листингах фреймворка показать, в чем же я не прав

Очевидно, что исходники фреймворка не могут являтся ни аргументами, ни показателем интенсивности моего чувства очевидности — уже передергиваешь. И тут же юлишь: я выдвинул утверждение о том, что твое заявление голословно, ты же, вместо аргументации в свою пользу, обвиняешь меня в том, что я не могу указать на твою не правоту.

SL>Есть код

SL>
SL>await Task.WhenAll(Task.Run(after1), Task.Run(after2), Task.Run(after3))
SL>

SL>а есть код
SL>
SL>Parallel.Invoke(after1, after2, after3)
SL>


И есть твои слова относительно этого кода:

Таски в обоих вариантах запускаются идентично.

Все еще их придерживаешься?

SL>Любому первокласснику очевидно, что это в обоих примерах по одной строке кода.


Не любому, а умеющему юлить и передергивать.

SL>Ну так казалось, до твоего "сравнения"...


Не до моего, а до твоего. Ты не сравнивал количество строк, но ты сравнивал одну строку с WhenAll и кусок фреймворка.

SL>Мы же не знали, что надо посмотреть, сколько строк занимает Parallel.Invoke, при этом не смотря на размер Task.WhenAll..


Конечно, потому что смотрели на вызов из одной строки и всю функцию.

SL>Только тогда станет очевидно, что второй пример в 198 раз больше!


Уже хорошо. А теперь расскажи как разный код, разного размера, обладающий разной функциональность может иметь в целом одинаковую полезную работу.

SL>Ясно, понятно. Я не терапевт, дальше бессилен.

SL>В дальнейшей беседе смысла не вижу: в мой адрес уже только и летят фразы "голословные обвинения", а вот с подкреплением делом этих слов пока движа нет

Ариведерчи
... << RSDN@Home 1.3.108 alpha 5 rev. 56>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.