Re[23]: Axum: паралельное программирование
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 16.05.09 15:49
Оценка:
Здравствуйте, eao197, Вы писали:

E>Мне кажется, что тотальная асинхронность все-таки лучше тотальной синхронности.


Лучше всего чтобы синхронность\асинхронность выражалась декларативно, а код был одинаковым в обоих случаях.
Re[24]: Axum: паралельное программирование
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 16.05.09 15:51
Оценка: :)
Здравствуйте, gandjustas, Вы писали:

E>>Мне кажется, что тотальная асинхронность все-таки лучше тотальной синхронности.


G>Лучше всего чтобы синхронность\асинхронность выражалась декларативно, а код был одинаковым в обоих случаях.


Ага, и все это на .NET-е


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[25]: Axum: паралельное программирование
От: Gaperton http://gaperton.livejournal.com
Дата: 16.05.09 15:55
Оценка: 31 (3)
Здравствуйте, eao197, Вы писали:

E>В общем, да. Поскольку ты говорил, что замерял затраты на асинхронный и синхронный подходы, то было бы интересно взглянуть на результаты замеров.


E>Поскольку в своих задачах я просто видел возможность их решения с помощью асинхронных агентов (с приемлимыми трудозатратами и качеством). Но не видел такой возможности с синхронными подходами. А возможности тратить месяц на получение и внедрение одного решения, а затем еще месяц на разработку альтернативы с целью сравнения разных подходов -- такой роскоши не бывает.


Короче. Код по понятной причине показать не могу. Но могу описать ситуацию. Дело было так.

В CQG в сервере БД для обработки временных рядов есть подсистема "операторов" (преобразований над временными рядами), которые умеют преобразовывать временную шкалу для временного ряда. То есть, на вход идет последовательность котировок, а на выход — другой временной ряд, состоящий, скажем, из значений, соответствующих периодам монотонного возрастания и убывания значений во временном ряде. Один участок монотонности — одно значение. Этот "оператор" называется P&F.

Практически весь код в CQG написан в "асинхронном" стиле. Один поток, много коллбэков, блокировать надолго процесс нельзя. Проблема, из-за которой мне было поручено переписать P&F, состояла в том, что время вычисления одного значения временного ряда в случае P&F могло быть очень длинным, а архитектура не предполагала, что можно прерваться в середине расчета одного значения временного ряда. "Конечные автоматы" высокого уровня такого не предполагали, и поправить это было очень сложно.

То есть, помимо того, чтобы разработать способ решения предыдущей проблемы (что к делу не совсем относится), мне надо было развернуть достаточно простой последовательный алгоритм P&F, который уже был написан и работал, и занимал примерно экран кода, в конечный автомат.

Автомат простой, в нем три состояния. Период убывания, возрастания, или "разгон". "Сообщениями" конечного автомата являлись значения временного ряда котировок. "Переход" конечного автомата — генерация нового выходного значения. Примерно так. На самом деле, все было чуточку сложнее, так как по некоторой причине надо было еще и "развернуть" алгоритм, чтобы он работал при подаче входных значений в обратном времени, но это не важно.

Я затрахался это отлаживать (там была иерархия автоматов, алгоритм был внизу, по другому нельзя). Это оказалось удивительно долго — я сорвал сроки. Однако, я предполагал, что за P&F последуют задания на аналогичную переделку других "операторов" данной группы, и оформил это безобразие как маленький фреймворк, чтобы иметь меньше геморроя при последующих работах. Если ты помнишь рассказы про мой шедулер — я его тогда и написал, в том варианте он просто "честно" шедулил время между коллбэками, без всяких файберов.

И когда последовало аналогичное задание "а теперь сделай то же самое для оператора CVB", я понял, что ЭТОТ алгоритм разворачивать в конечный автомат я не хочу. И прикрутил к шедулеру файберы. В сроки, однако, заложил охрененные "буфера безопасности". Получилось однако, по оптимистичному прогнозу.

Потом, последовало еще два оператора. И я получил возможность оценить объем кода и сроки — у меня есть старый синхронный код, который писал не я, а также новый "асинхронный" и "синхронный" код. Разница оказалась примерно в два раза, при наличии корелляции с объемом кода. Что меня удивило. Ибо, по ощущениям и по количеству геморроя в P&F пошел месяц за два . Я ожидал разницы в четверо.

Сроки были порядка месяцев. Примерно две недели на оператор в синхронном варианте, без явных конечных автоматов, и месяц — на "асинхронный" вариант. Это чистая логика алгоритма. Учти, что я на тот момент очень хорошо умел писать асинхронный конечно-автоматный код. Количество строк кода — не помню. Помню вывод.

Потом, я многократно проверял этот вывод на практике, при случае, когда надо что-то порефакторить, заменяя старый асинхронно-коллбэчный код (которого в системе дофига) на новый "синхронный" код. Разница в читабельности и объеме поистине удивительная. Все та же, впрочем, в объеме — в среднем примерно в два раза.

E>>>Спасибо, я и сам понимаю его достоинства и недостатки. Тем не менее, я не разделяю твоей уверенности в том, что есть какой-то единственный правильный подход к реализации агентов.


G>>Я, вообще-то, этого не говорил.


E>Ну, поскольку мой подход ты называешь плохим, значит, по твоему мнению есть хотя бы один более хороший. С этим я не согласен. Плохость в одних задачах оборачивается хорошестью в других, и наоборот.


Да. У тебя "асинхронный" подход, которого я нахлебался по самые уши. Я тебе в другом посте объяснил.
Re[25]: Axum: паралельное программирование
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 16.05.09 15:55
Оценка:
Здравствуйте, eao197, Вы писали:

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


E>>>Мне кажется, что тотальная асинхронность все-таки лучше тотальной синхронности.


G>>Лучше всего чтобы синхронность\асинхронность выражалась декларативно, а код был одинаковым в обоих случаях.


E>Ага, и все это на .NET-е


Угу, Axum так умеет.

Синхронное и асинхронное копирование данных из одного стрима в другой на Axum
    private void CopyStream( Stream source, Stream destination )
    {
        byte[] buffer = new byte[1024];
        int bytesRead = 0;
        
        while((bytesRead = source.Read( buffer, 0, 1024)) != 0 )
        {
            destination.Write( buffer, 0, bytesRead );
        }
    }
    
    private asynchronous void CopyStreamAsync( Stream source, Stream destination )
    {
        byte[] buffer = new byte[1024];
        int bytesRead = 0;
        
        while((bytesRead = source.Read( buffer, 0, 1024)) != 0 )
        {
            destination.Write( buffer, 0, bytesRead );
        }
    }
Re[26]: Axum: паралельное программирование
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 16.05.09 16:05
Оценка:
Здравствуйте, Gaperton, Вы писали:

G>Короче. Код по понятной причине показать не могу. Но могу описать ситуацию. Дело было так.


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

Кстати, судя по описанию задачи, я бы не рекомендовал сходу использовать для P&F мой подход, т.к. он гораздо лучше подходит для "тяжелых" сообщений-заданий или уведомлений. Преобразовывать последовательности временных рядов в сообщения sobjectizer-агентов невыгодно. В том числе и из-за слишком большого "синтаксического оверхеда" в коде sobjectizer-агентов.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[23]: Axum: паралельное программирование
От: Gaperton http://gaperton.livejournal.com
Дата: 16.05.09 16:09
Оценка:
Здравствуйте, eao197, Вы писали:

G>>Когда возникает такая необходимость, у тебя есть два варианта.

G>>1) Разбить одного агента на два (подставь нужное число), где все приведется к синхронному случаю.

E>Это черевато ситуациями, где несколько агентов должны разделять один блок общих данных. Здесь всплывает проблема организации синхронизации доступа к этим данным.


Есть такое дело. Это, в свою очередь, можно решить:
1) Явными синхронизациями на разделяемой памяти. Что, конечно, плохо, ибо непонятно, за что боролись, не так ли? Или же... удивительно, что есть какое-то "или", правда? А таки да, есть!
2) Апартментами. Апартментами, уважаемые коллеги! На чем и остановимся.

Короче, в COM есть прикольнейшая вешь, под названием single-threaded appartment. Это, вероятно, лучшая идея, которая есть в COM. И мы ее поюзаем, в несколько видоизмененном виде.

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

Когда ты расщепляешь для простоты агента на несколько — они живут в одном апартменте. И все.

G>>2) Использовать стиль "wait_for_multiple_ojects". То есть, ты блокируешься в одном вызове, ожидая любого из перечисленных событий.


E>У меня этот стиль выбран в качестве основного. Только в нем сам фреймворк выполняет ожидание и диспетчеризацию полученных сообщений с учетом текущего состояния агента (под состоянием понимается не содержимое его атрибутов и локальных переменных).


Я это понял.

G>>Понимаешь, в чем дело. Во-первых, не хочется, чтобы простые случаи затуманивали на ровном месте код, вызывая у читателя шок и трепет. Раз они простые — почему бы им и не выглядеть просто.


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


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

G>>А для сложного случая — что мне мешает сделать по месту и необходимости message loop и использовать твой стиль (кстати, во многих случаях я этого смогу избежать, расщепив агента на несколько)?


E>Одной из целей было освобождение разработчика от необходимости взаимодействия с message loop вообще. И, как следствие, от избавления от спагети-кода, в который, как правило, превращается при сопровождении работа с message loop.


Мессадж луп можно записать очень просто, если об этом специально позаботится. Да хоть твоими же макросами, только не в определении класса, а в определении функции, вот и вся разница. Кстати, макросов при этом потребуется поменьше.

G>>Получается, что я могу комбинировать оба подхода, а ты привязан к одному из них. Хорошо ли это?


E>Мне кажется, что тотальная асинхронность все-таки лучше тотальной синхронности.


А я вижу очень большое преимущество в возможности комбинирования обоих подходов.
Re[27]: Axum: паралельное программирование
От: Gaperton http://gaperton.livejournal.com
Дата: 16.05.09 16:15
Оценка:
Здравствуйте, eao197, Вы писали:

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


G>>Короче. Код по понятной причине показать не могу. Но могу описать ситуацию. Дело было так.


E>Все это интересно, но ты судишь на основании, я бы сказал, достаточно частного опыта.


Все мы судим на основании частного опыта. Мой опыт основан на аппликухе размером в 2.5 миллиона строк кода, которая целиком написана в асинхронном стиле. То есть, я "накушался" именно такого подхода, о котором идет речь, в разных позах, по самые гланды. Там вообще не только P&F был, я там как-никак 6 лет проработал . Там были и "протокольные" задачи тоже, которые как раз неплохо в виде явного КА записывать. Во избежание.

E>Кстати, судя по описанию задачи, я бы не рекомендовал сходу использовать для P&F мой подход, т.к. он гораздо лучше подходит для "тяжелых" сообщений-заданий или уведомлений. Преобразовывать последовательности временных рядов в сообщения sobjectizer-агентов невыгодно. В том числе и из-за слишком большого "синтаксического оверхеда" в коде sobjectizer-агентов.


Я тоже не рекомендовал бы. Но куда программист денется, если ты другого подхода не даешь? Вот я и говорю, лучше комбинированный подход использовать. Когда у тебя состояние "агента" хранится на стеке, как например в Эрланге, это дает возможность выбирать подход по месту.
Re[24]: Axum: паралельное программирование
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 16.05.09 16:17
Оценка:
Здравствуйте, Gaperton, Вы писали:

G>Когда ты расщепляешь для простоты агента на несколько — они живут в одном апартменте. И все.


Когда они живут на одном контексте, то они не могут просто так "заснуть" на блокирующем синхронном вызове и при этом сохранять свое состояние на стеке. Потребуются системно-зависимые хаки для копирование стека заснувшего агента и передачи его контекста другому агенту.

Хотя я мог тебя неправильно понять.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[25]: Axum: паралельное программирование
От: Gaperton http://gaperton.livejournal.com
Дата: 16.05.09 16:26
Оценка:
Здравствуйте, eao197, Вы писали:

G>>Когда ты расщепляешь для простоты агента на несколько — они живут в одном апартменте. И все.


E>Когда они живут на одном контексте, то они не могут просто так "заснуть" на блокирующем синхронном вызове и при этом сохранять свое состояние на стеке. Потребуются системно-зависимые хаки для копирование стека заснувшего агента и передачи его контекста другому агенту.


В винде для C/C++ это делается без каких-либо хаков, через стандартный API, при задействовании Fibers.

В Linux/Unix для C/C++ это должно делаться также без каких-либо хаков, через так называемые user-level threads.

В языках, которые поддерживают continuations, это можно сделать через них. Опять же, без хаков. Continuations это достаточно распространенная штука — я слышал, например, что так можно делать в Smalltalk, LISP, и JavaScript.

А вот в .NET такого штатными средствами сделать нельзя . По крайней мере, я год назад пытался найти в сети отчет о применении такого способа — не нашел .

E>Хотя я мог тебя неправильно понять.


Ты правильно меня понял. Да, для этого фокуса требуется уметь сохранять и переключать локальный контекст.
Re[28]: Axum: паралельное программирование
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 16.05.09 16:28
Оценка:
Здравствуйте, Gaperton, Вы писали:

G>Все мы судим на основании частного опыта. Мой опыт основан на аппликухе размером в 2.5 миллиона строк кода, которая целиком написана в асинхронном стиле.


Я с 1997-го работаю со своим (точнее, он не мой, просто мной реализован) подходом. На различных проектах, от управления технологическими процессами до электронной коммерции.

G>Я тоже не рекомендовал бы. Но куда программист денется, если ты другого подхода не даешь?


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

В библиотеке ACE реализован специальный паттерн (вроде там это называется streams framework). Когда каждая стадия обработки потока данных оформляется в виде специального модуля (наследника ACE_Service_Object, кажется), а все взаимодействие строится на основе ручного помещения и извлечения сообщений в очереди сообщений. Такой подход хорошо подходит для решения различных задач. А SObjectizer является альтернативой такому streams framework-у.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[29]: Axum: паралельное программирование
От: Gaperton http://gaperton.livejournal.com
Дата: 16.05.09 16:35
Оценка:
Здравствуйте, eao197, Вы писали:

G>>Я тоже не рекомендовал бы. Но куда программист денется, если ты другого подхода не даешь?


E>Мой подход можно пременять только для "крупноблочного" строительства. А внутри каждого блока использовать то, что будет наилучшим выбором.


Добавь в него файберы, как в свое время сделал я, будет прикольно, полезно, и удобно. Это можно сделать ничего не сломав. И сможешь сочетать оба подхода. Если, конечно, у тебя нет идиосинкразии у Эрлангу .
Re[30]: Axum: паралельное программирование
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 16.05.09 16:40
Оценка:
Здравствуйте, Gaperton, Вы писали:

E>>Мой подход можно пременять только для "крупноблочного" строительства. А внутри каждого блока использовать то, что будет наилучшим выбором.


G>Добавь в него файберы, как в свое время сделал я, будет прикольно, полезно, и удобно. Это можно сделать ничего не сломав. И сможешь сочетать оба подхода.


Поживем -- увидим.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[20]: Axum: паралельное программирование
От: Gaperton http://gaperton.livejournal.com
Дата: 16.05.09 16:53
Оценка:
Здравствуйте, Gaperton, Вы писали:

G> Скажем, подумай на досуге немного о том, почему и зачем в Эрланге сделан селективный receive на одном мэйлбоксе, а не по другому. Hint — это решение сильно упрощает код в реальных программах.


Коль скоро у нас кровавого мочилова нет, то я сам отвечу на этот вопрос

Штука в том, что селективный receive позволяет не заботится о порядке, в котором приходят сообщения. Пример:
Допустим, к нам могут прийти два сообщения, A и B. Прийти они могут в любом порядке, однако, по логике обработки мы должны сначала дождаться A, а только потом — B.

В Эрланге мы в этом случае так и пишем:
receive { msg_A, Body } -> process( Body ) end,
receive { msg_B, Body } -> process( Body ) end,


То есть, мы не должны явно обрабатывать обе ситуации, когда сначала приходит A а потом B, и наоборот. Код одинаков и весьма прямолинеен. И нам все равно, в каком порядке на самом деле они придут. Если B придет раньше A, оно просто полежит в мэйлбоксе до тех пор, пока его не заберут.

Еще один пример. Нам надо дождаться, когда придут все сообщения от "агентов" из списка, и только потом продолжать. Что мы делаем — мы в их тупо получаем в цикле, перебирая агентов из списка.

MsgList = [ receive { From, Body } -> Body end || From <- WaitingAgentsList ]


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

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

Хорошее свойство.
Re[26]: Axum: паралельное программирование
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 16.05.09 16:55
Оценка:
Здравствуйте, Gaperton, Вы писали:

E>>Хотя я мог тебя неправильно понять.


G>Ты правильно меня понял. Да, для этого фокуса требуется уметь сохранять и переключать локальный контекст.


Я ошибся. Почему-то стал считать, что аппартментом может быть один фибер для нескольких агентов. Поскольку, если каждому из мелких агентов дать по своему файберу, то нужно будет следить за тем, чтобы они запускались только на контексте одной нити. Тогда как могли бы быть ситуации, когда выгодно было бы дать таким файберам работать параллельно на разных нитях. Но такой сценарий, при некотором размышлении, не выглядит слишком реалистичным.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[21]: Axum: паралельное программирование
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 16.05.09 16:59
Оценка:
Здравствуйте, Gaperton, Вы писали:

G>> Скажем, подумай на досуге немного о том, почему и зачем в Эрланге сделан селективный receive на одном мэйлбоксе, а не по другому. Hint — это решение сильно упрощает код в реальных программах.


G>Коль скоро у нас кровавого мочилова нет, то я сам отвечу на этот вопрос


Всю эту бодягу, AFAIK, сам Джо Армстронг уже расписывал. Может быть даже неоднократно

G>Хорошее свойство.


Сильно сомневаюсь, по крайней мере на основании своего опыта.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[27]: Axum: паралельное программирование
От: Gaperton http://gaperton.livejournal.com
Дата: 16.05.09 17:07
Оценка:
Здравствуйте, eao197, Вы писали:

E>>>Хотя я мог тебя неправильно понять.


G>>Ты правильно меня понял. Да, для этого фокуса требуется уметь сохранять и переключать локальный контекст.


E>Я ошибся. Почему-то стал считать, что аппартментом может быть один фибер для нескольких агентов. Поскольку, если каждому из мелких агентов дать по своему файберу, то нужно будет следить за тем, чтобы они запускались только на контексте одной нити.


Да, вот теперь ты точно правильно меня понял. Именно так. Всегда один агент — один файбер, много агентов — один апартмент, и ни в коем случае не пускать больше одного треда одновременно в каждый апартмент. Ибо нефиг.

E>Тогда как могли бы быть ситуации, когда выгодно было бы дать таким файберам работать параллельно на разных нитях. Но такой сценарий, при некотором размышлении, не выглядит слишком реалистичным.


Совершенно верно. Реальный параллелизм в данном случае, ровно так же как и в COM, делается апартментами. Это не так страшно, ибо в серверных задачах тебе почти всегда хватит реального параллелизма на уровне клиентских сессий. Их всегда больше, чем процессоров.

Пример из телефонии. Один апартмент — один разговор. В апартменте живет один "главный" агент, и по одному "агенту на каждого участника разговора. Ответственность агентов-участников — они обрабатывают управляющий протокол точка-точка с IP-телефоном участника (это SIP-сессия), в то время как "главный" управляет всей конференцией-разговором, координируя агентов-участников, обеспечивая, например, добавление новых, и отключение текущих участников.

Скажем, при появлении нового участника конференции надо замогильным голосом всем объявить, что к нам присоединился новый участник. Эту процедуру инициирует "главный".

Смысл разделения на группу агентов в данном примере понятен — во первых, по своей семантике они независимы и параллельны, во вторых — мы таким шагом радикально упрощаем запись конечных автоматов.

Короче, это хорошее, годное решение .
Re[26]: Axum: паралельное программирование
От: Gaperton http://gaperton.livejournal.com
Дата: 16.05.09 17:44
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Угу, Axum так умеет.


G>Синхронное и асинхронное копирование данных из одного стрима в другой на Axum


Занятно. И что именно он сделает с моим кодом, если я напишу asynchronous? Это поддается осмыслению?
Re[27]: Axum: паралельное программирование
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 16.05.09 18:01
Оценка:
Здравствуйте, Gaperton, Вы писали:

G>Занятно. И что именно он сделает с моим кодом, если я напишу asynchronous? Это поддается осмыслению?


Если я правильно понимаю, то при вызове CopyStreamAsync сам ран-тайм произведет вызов на одной из рабочих нитей из пула. Т.е. вызывающей стороне всего лишь не придется вручную бабахаться с оформлением фьючерса.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[22]: Axum: паралельное программирование
От: Gaperton http://gaperton.livejournal.com
Дата: 16.05.09 18:03
Оценка:
Здравствуйте, eao197, Вы писали:

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


G>>> Скажем, подумай на досуге немного о том, почему и зачем в Эрланге сделан селективный receive на одном мэйлбоксе, а не по другому. Hint — это решение сильно упрощает код в реальных программах.


G>>Коль скоро у нас кровавого мочилова нет, то я сам отвечу на этот вопрос


E>Всю эту бодягу, AFAIK, сам Джо Армстронг уже расписывал. Может быть даже неоднократно


Ну, в общем, да, кто-то из них объяснял. Я это читал когда-то в сообщениях Ульфа Вигерса в мэйллисте. Я же не знаю, знаком ты с этим тезисом или нет. Ментальным сканированием не владею. Опять же, может кому еще интересно будет.

G>>Хорошее свойство.


E>Сильно сомневаюсь, по крайней мере на основании своего опыта.


Знаешь, по крайней мере это не плохое свойство . Автоматическая неявная синхронизация, которую мы имеем без каких-либо умственных затрат в данном случае — чем плоха?
Re[28]: Axum: паралельное программирование
От: Gaperton http://gaperton.livejournal.com
Дата: 16.05.09 18:06
Оценка:
Здравствуйте, eao197, Вы писали:

G>>Занятно. И что именно он сделает с моим кодом, если я напишу asynchronous? Это поддается осмыслению?


E>Если я правильно понимаю, то при вызове CopyStreamAsync сам ран-тайм произведет вызов на одной из рабочих нитей из пула. Т.е. вызывающей стороне всего лишь не придется вручную бабахаться с оформлением фьючерса.


Какое-то получается весьма сомнительное преимущество. Которое скорее затруднит чтение кода, чем сделает его более понятным. Уж лучше тупо фьючерсы на уровне языка поддержать, чтоб не заставлять программиста сильно бабахаться с его оформлением, и не морочить людям голову.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.