Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
V>>>О том и речь... Не катит. G>>Ты о чем?
V>Нетипизировано (согласен, возразили), но размер кода будет в итоге такой же, как в некоторых приведенных декомпозициях, например последний вариант здесь: http://www.rsdn.ru/forum/dotnet/4696155.1.aspx
V>Т.е. смысла нет.
Вообще-то твой код задачу не решает Кроме того у тебя логика дублирована, и частично находится внутри коллбеков.
Небольшое изменение логики и все переписывать. Rx и TPL таким не страдают.
G>>Только тебе придется такой код писать для каждой последовательности, потому что у тебя проверки внутри коллбеков. А Observable обертка может быть тупо сгенерирована один раз. V>Покажи каким образом, если каждый раз вызываются разные методы и подписка идет к разным событиям?
Статически сгенерировать нужные экстеншены. Есть даже такая утилита для событий UI. сове сделать один раз совсем несложно.
Re[12]: Лавинообразная сложность асинхронных методов
От:
Аноним
Дата:
10.04.12 13:57
Оценка:
Здравствуйте, gandjustas, Вы писали: G>Небольшое изменение логики и все переписывать. Rx и TPL таким не страдают.
Абсолютно то же самое без всякого Rx. Что именно Rx упростил? В каком месте?
Зачем тянуть еще и Rx, если абсолютно то же самое можно написать без него??? G>Статически сгенерировать нужные экстеншены. Есть даже такая утилита для событий UI. сове сделать один раз совсем несложно.
Кто такая "сова"?
Re[13]: Лавинообразная сложность асинхронных методов
От:
Аноним
Дата:
10.04.12 14:16
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Абсолютно то же самое без всякого Rx. Что именно Rx упростил? В каком месте? А>Зачем тянуть еще и Rx, если абсолютно то же самое можно написать без него???
Именно об этом я и писал выше: пробовал писать по разному, в т.ч. задействовать Rx -- ничего не помогло избавиться от макарон неоправданной сложности. То есть код перестает быть прозрачным -- в нем легко запутаться и чего-то не увидеть.
Ваш вариант с Rx абсолютно ничем не отличается от приведенного мной варианта с Action. И мой вариант с Action по своей сути ничем не отличается от варианта №2 отсюда: http://rsdn.ru/forum/dotnet/4695359.aspx?tree=tree
(только вместо Action используются обычные методы).
Может вы видите разницу? Кроме того, что кто-то начинает "срать кирпичами" от того, что удалось применить супер модную тезнологию Rx -- какой то еще профит есть???
Принципиальной разницы между ними нет -- сложность та же самая. Получается неоправданно сложно на пустом месте.
Здравствуйте, Аноним, Вы писали:
А>Но таким как вы это очень сложно увидеть. Вам MS будет сцать на голову -- а вы будете говорить "Божия роса".
Ничуть. Например, сокеты в линуксе мне нравятся больше, чем в WinSock (имеется ввиду C без "шарпности"). Вот такая вот "роса".
Более того — это сейчас пишется из-под Линукса (не виртуалка!), на котором бежит RDP с виндой
Re[13]: Лавинообразная сложность асинхронных методов
Здравствуйте, Аноним, Вы писали:
А>И, собственно, вопрос. Что делать, если таких вот Action в проекте действительно много? Как быть, как написать? Это ж идиотизм какой-то.
Я бы использовал F#, и фиг с ним, что FSharp.Core.dll для WP7 весит 930 килобайт. Зато асинхронный код выглядит внешне практически так же, как и синхронный из твоего примера.
Re[14]: Лавинообразная сложность асинхронных методов
Здравствуйте, hardcase, Вы писали:
H>Это вполне нормальная практика, она называется "рукопашное CPS-преобразование". Примерно тоже самое с кодом производит грядущий async/await.
Нет. Версия для C# отличается. У них async/await реализуется не через продолжения как в F#, а через конечный автомат. Есть свои плюсы и минусы. В Немерле тоже сделано по особому.
Re[13]: Лавинообразная сложность асинхронных методов
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, gandjustas, Вы писали:
G>>Небольшое изменение логики и все переписывать. Rx и TPL таким не страдают.
А>Абсолютно то же самое без всякого Rx. Что именно Rx упростил? В каком месте?
В rx очень легко будет записать последовательность операций когда вызов следующей зависит от предыдущей.
А>Зачем тянуть еще и Rx, если абсолютно то же самое можно написать без него???
Тоже самое нельзя — небольшое изменение и вся "красота" рассыпится.
G>>Статически сгенерировать нужные экстеншены. Есть даже такая утилита для событий UI. сове сделать один раз совсем несложно. А>Кто такая "сова"?
Наверное "такое"
Re[2]: Лавинообразная сложность асинхронных методов
L>Не факт, что их ответ вам подойдет на 100%, но чем черт не шутит.
Уж послал так послал
Народная мудрось
всем все никому ничего(с).
Re[14]: Лавинообразная сложность асинхронных методов
От:
Аноним
Дата:
10.04.12 16:47
Оценка:
Здравствуйте, gandjustas, Вы писали:
А>>Зачем тянуть еще и Rx, если абсолютно то же самое можно написать без него??? G>Тоже самое нельзя — небольшое изменение и вся "красота" рассыпится.
Например что? Передать аргументы? Разве сложно?
G>>>Статически сгенерировать нужные экстеншены. Есть даже такая утилита для событий UI. сове сделать один раз совсем несложно. А>>Кто такая "сова"? G>Наверное "такое"
Ну и что такое "сове"? Интересно просто -- совсем не понятен смысл предложения...
Re[6]: yield return вместо async/await
От:
Аноним
Дата:
10.04.12 18:30
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:
MD>Ничуть. Например, сокеты в линуксе мне нравятся больше, чем в WinSock (имеется ввиду C без "шарпности"). Вот такая вот "роса". MD>Более того — это сейчас пишется из-под Линукса (не виртуалка!), на котором бежит RDP с виндой
Тогда приведите аргументы "за" вырезание синхронных методов.
Это удобно лишь для тривиальных случаев. Для сложных случаев такая "помощь" лишь приводит к значительному усложнению.
Ваш аргумент -- мол "индусы увидят и испугаются и уйдут с отрасли" -- как минимум глуп. Напугай ежика голой попой называется... Индусы будут делать лапша-код. И он будет зависать, т.к. наверняка добавят рекурсивные вызовы и оно у них будет периодически зациклиться.
Так что со всех сторон плохо: и добавляет лишнего геммора и от индусов не избавляет.
Re[12]: Лавинообразная сложность асинхронных методов
G>Кроме того у тебя логика дублирована, и частично находится внутри коллбеков.
Я уже напомнил, что всего 3 ветки, чтобы не увлекался рассуждениями в эту область. Как надо делать если однотипных задач будет больше — ответил там же, как раз то место, которое ты скипнул.
G>Небольшое изменение логики и все переписывать. Rx и TPL таким не страдают. G>>>Только тебе придется такой код писать для каждой последовательности, потому что у тебя проверки внутри коллбеков. А Observable обертка может быть тупо сгенерирована один раз. V>>Покажи каким образом, если каждый раз вызываются разные методы и подписка идет к разным событиям? G>Статически сгенерировать нужные экстеншены. Есть даже такая утилита для событий UI. сове сделать один раз совсем несложно.
Здравствуйте, Аноним, Вы писали:
А>Тогда приведите аргументы "за" вырезание синхронных методов. А>Это удобно лишь для тривиальных случаев. Для сложных случаев такая "помощь" лишь приводит к значительному усложнению.
Со временем прихожу к обратному выводу. Синхронный вызов не имеет никаких гарантий максимального времени работы. В тривиальном случае — предсказуемо, но при сложении ряда факторов — взрыв временнОй сложности.
Конкретный пример — Eclipse. Святая в своей простоте идея — показывать юзеру список доступных плагинов и обновлений, далее путём ввода ключевых слов юзер на лету фильтрует всё что надо и тыкает мышкой в галочки, затем жмёт Install. Вписал слово XML — на тебе все XML-плюшки, вписал WTP — показывается Web Tools Platform, ну и так далее. На практике имеем некрасивые тормоза.
Сам по себе список плагинов — летает как надо (видимо, он виртуальный, без запихивания всех строк физически в контрол). Но фильтрация — мамма миа, при большом количестве доступных источников плагинов начинается размышлёж на несколько минут, и это на i7-930 — четыре HT-ядра, т.е. восемь[!] конвейров. Само собой, тут же оказывается, что семь конвейров стоят без дела, а восьмой ушивается в усмерть одним синхронным вызовом (тривиальным, но многоповторным циклом)... UI при этом дохлый, прервать нельзя (точнее, нажатие на ESC будет обработано позднее, сразу по окончании этой мега-фильтрации, разом убивая все результаты поиска). Понятно, что надо бы вынести в поток, и всё такое, но... В общем случае, как программисту угадать, что вызов foo() будет долгоиграющим? Правильно, никак. И тут нам на помощь должен прийти системный API, который автоматически будет подразумевать, что клиенту вернут асинхронный fooStart(), а далее будь добр, дорогой мистер бобр, отметить себе нужный state и ждать нотификации fooEnd().
Кстати, идея слежения за максимальной длительностью вызова — не нова в мобильном мире. Ещё старик Symbian умел удушать любой процесс, главный поток которого жрал более 20 секунд времени. Андроид тоже мониторит загруз CPU, и при повышенных аппетитах приложений может тупо уйти в ребут. Так что, MS тут ничего нового не изобрел.
1. Если есть возможность вынести эту логику в отдельный метод сервиса (этого или другого) тогда все упрощаеться до вызова одного метода и обработки результата.
2. Решение на клиенте в лоб (лучше написать или сгенерировать обертку под каждый метод):
private static AutoResetEvent _resetEvent = new AutoResetEvent(false);
private static void Main(string[] appArgs)
{
// Задача: вызывать Fun 1 и получить "n".
//
// После этого последовательны должны быть вызваны:
//
// Action2 (кроме случаев, когда "n" не делится на 2)
// Action3 (кроме случаев, когда "n" не делится на 3)
// Action4 (кроме случаев, когда "n" не делится на 4)var service = new Service();
// Асинхронный вариант 1var n = -1;
_resetEvent.Reset();
service.FunCompleted += (sender, args) =>
{
n = args.Argument;
_resetEvent.Set();
};
service.StartFun();
_resetEvent.WaitOne();
//или сделав обертку так
n = FunWrapper(service);
//подписка на Completed
service.Action2Completed += Service_ActionCompleted;
service.Action3Completed += Service_ActionCompleted;
service.Action4Completed += Service_ActionCompleted;
if (0 == n % 2)
{
service.StartAction2();
_resetEvent.WaitOne();
}
if (0 == n % 3)
{
service.StartAction3();
_resetEvent.WaitOne();
}
if (0 == n % 4)
{
service.StartAction4();
_resetEvent.WaitOne();
}
Console.WriteLine("Complete");
}
private static void Service_ActionCompleted(object sender, EventArgs e)
{
_resetEvent.Set();
}
private static int FunWrapper(Service service)
{
var resetEvent = new AutoResetEvent(false);
int result = -1;
service.FunCompleted += (sender, args) =>
{
result = args.Argument;
resetEvent.Set();
};
service.StartFun();
resetEvent.WaitOne();
return result;
}
Здравствуйте, Mr.Delphist, Вы писали:
MD>В общем случае, как программисту угадать, что вызов foo() будет долгоиграющим? Правильно, никак.
Не правильно. Для этого нужно иметь голову на плечах.
Вы что предлагаете "на всяких случай" делать исключительно асинхронный вариант для всех методов, которые могут выполняться долго?
Тогда сделайте это для методов:
1. Работы с базой данных -- запросы ведь тоже длительные бывают.
2. Для чтения файла.
3. Да чего уж там -- вообще отменить все синхронные вызовы -- вдруг в каком-то методе длительные вычисления а программист то об этом и не знает...
В том то и соль -- голова на плечах дана для того, чтобы обернуть в асинхронный вызов именно ту операцию, которую требуется.
MD>Кстати, идея слежения за максимальной длительностью вызова — не нова в мобильном мире. Ещё старик Symbian умел удушать любой процесс, главный поток которого жрал более 20 секунд времени. Андроид тоже мониторит загруз CPU, и при повышенных аппетитах приложений может тупо уйти в ребут. Так что, MS тут ничего нового не изобрел.
Пусть следят -- я не против. Закрывают программы, которые тормозят UI-поток или чрезмерно расходуют CPU. Но не нужно усложнять на пустом месте.
Так бы я написал все простым синхронным способом и обернул все в одну асинхронную обертку (чтобы не выполнялось в UI-потоке). А теперь куча дерьма + еще время на переключение потоков тратиться (а это доп. ресурсы, кстати).
Re[2]: Лавинообразная сложность асинхронных методов
От:
Аноним
Дата:
10.04.12 22:13
Оценка:
Здравствуйте, Andrey-D, Вы писали:
AD>2. Решение на клиенте в лоб (лучше написать или сгенерировать обертку под каждый метод):
Это было первой мыслью. Но, к сожалению, не работает -- зависает. Вызов FunCompleted вызывается в UI-потоке, а он заблокирован _resetEvent.WaitOne().
Re[3]: Лавинообразная сложность асинхронных методов
А как ты проверяешь?
На тесте консолька+веб сервис вызов FunCompleted идет в отдельнои потоке.
А>Здравствуйте, Andrey-D, Вы писали:
AD>>2. Решение на клиенте в лоб (лучше написать или сгенерировать обертку под каждый метод):
А>Это было первой мыслью. Но, к сожалению, не работает -- зависает. Вызов FunCompleted вызывается в UI-потоке, а он заблокирован _resetEvent.WaitOne().
Re[13]: Лавинообразная сложность асинхронных методов
G>>Кроме того у тебя логика дублирована, и частично находится внутри коллбеков. V>Я уже напомнил, что всего 3 ветки, чтобы не увлекался рассуждениями в эту область. Как надо делать если однотипных задач будет больше — ответил там же, как раз то место, которое ты скипнул.
Это придется гораздо больше писать.
G>>Небольшое изменение логики и все переписывать. Rx и TPL таким не страдают. G>>>>Только тебе придется такой код писать для каждой последовательности, потому что у тебя проверки внутри коллбеков. А Observable обертка может быть тупо сгенерирована один раз. V>>>Покажи каким образом, если каждый раз вызываются разные методы и подписка идет к разным событиям? G>>Статически сгенерировать нужные экстеншены. Есть даже такая утилита для событий UI. сове сделать один раз совсем несложно. V>Ну так покажи как это будет выглядеть. Любопытно.
Ты быстрее сам примеры в сети найдешь, чем я буду писать.
Если уж очень интересно — подожди.
Re[4]: Лавинообразная сложность асинхронных методов
От:
Аноним
Дата:
10.04.12 22:54
Оценка:
Здравствуйте, Andrey-D, Вы писали:
AD>А как ты проверяешь? AD>На тесте консолька+веб сервис вызов FunCompleted идет в отдельнои потоке.
На эмуляторе Windows Phone7. Там почему то так.
Re[14]: Лавинообразная сложность асинхронных методов
G>>>Кроме того у тебя логика дублирована, и частично находится внутри коллбеков. V>>Я уже напомнил, что всего 3 ветки, чтобы не увлекался рассуждениями в эту область. Как надо делать если однотипных задач будет больше — ответил там же, как раз то место, которое ты скипнул. G>Это придется гораздо больше писать.
А что, есть варианты? Разве есть типизированный способ декларативно привязаться к событию чужого объекта? Проблема примера в том, в том, что асинхронные методы целевого объекта не соответствуют асинхронному паттерну. Т.е. вместо того, чтобы подавать AsyncCallback прямо в вызов метода, приходится подписываться на какое-то мифическое событие. Вот и получил ручную писанину и прочие макароны.
V>>Ну так покажи как это будет выглядеть. Любопытно. G>Ты быстрее сам примеры в сети найдешь, чем я буду писать.
Разве? Мне был интересен момент декларативной подписки на события для заданного примера.