Комментарии 62
А откуда именно потом будет вызвано continuation? Из главного event loop-а?
+2
ну будет наверно какой-нить Dispatcher как в WPF, который будет в event loop вызываться.
+2
Да я просто думаю, делать логику сервачка по-старинке через yield или таки попробовать использовать async. С yield не будет лишних потоков, а вот как работает с сокетами async, пока не ясно.
0
Из System.Threading.SynchronizationContext.Current
+1
Отлично, а его кто пинает? Ну не может быть такого, чтобы посреди выполнения кода (который вполне может быть внутри какой-нибудь блокировки) его прерывали и переключали контекст на continuation.
+1
Если я все правильно помню, для не UI кода по умолчанию это все реализовано через ThreadPool и егошний диспетчер, т.е. никакой код не прерывается, просто берется свободный поток из пула или создается новый. В случае с UI — используется Dispatcher UI фреймворка (WinForms, WPF, SL), чтобы обеспечить выполнения продолжения в контексте UI потока.
+2
Так оно в итоге только для UI-потоков гарантирует, что continuation будет вызван в том же потоке, в котором вызвали метод через await?
0
Не совсем. По умолчанию для не UI потоков не задан какой-то специфичный SynchronizationContext, поэтому выполнение идет через TaskScheduler.Current, который просто раскидывает задачи по потокам из пула. Но у вас всегда есть возможность задать свой SynchronizationContext, в котором определить требуемое поведение.
+1
В С++11 появилась схожая штука: ::std::async.
Передав в нее функцию, на выходе получаем ::std::future (continuation вообщем-то).
Пока результат нам не нужен — делаем посторонние задачи. Как нужен — вызываем метод get() у ::std::future, который или сразу вернет результат (если он уже посчитан) или заблокируется пока результата не будет.
К чему я это — к тому что асинхронность добавляется в разные языки, а значит набирает популярность у неискушенных программистов.
Передав в нее функцию, на выходе получаем ::std::future (continuation вообщем-то).
Пока результат нам не нужен — делаем посторонние задачи. Как нужен — вызываем метод get() у ::std::future, который или сразу вернет результат (если он уже посчитан) или заблокируется пока результата не будет.
К чему я это — к тому что асинхронность добавляется в разные языки, а значит набирает популярность у неискушенных программистов.
+2
Аналог того, что вы описали, было в C# задолго до async/await.
+3
А в чем тут отличие? Я с Си-шарпом только в универе был знаком.
0
Ну была штука под называнием IAsyncResult, которую возвращали асинхронные методы. Очень давно была.
+2
Любые методы или какие-то специально написанные? Если любые — так это понятно, это особенность конкретной библиотеки. А ::std::async это особенность языка — он принимает любую синхронную функцию, кладет ее в очередь, занимается пулом потоков — это все теперь проблемы языка и реализации стандартной библиотеки.
0
Тьфу, наоборот
>> Если любые — так это понятно
Следует понимать как
>> Если специально написанные — так это понятно.
Да, я посмотрел IAsyncResult ну это просто стандартный интерфейс под хэндл, а не механизм же.
>> Если любые — так это понятно
Следует понимать как
>> Если специально написанные — так это понятно.
Да, я посмотрел IAsyncResult ну это просто стандартный интерфейс под хэндл, а не механизм же.
0
Можно брать _любую_ функцию и вызывать ее через делегат
0
Ок. Посмотрю еще. А чем отличается от нововведения, описанного в статье?
0
Там просто запуск кода в фоне с возможностью потом его синхронно подождать. Описанное в статье возвращает выполнение в вызывающий код сразу, а уже потом из event-loop-а будет вызван обработчик результата, причём сам код пишется так, как будто он синхронный.
0
Ну вот вы писали "… который или сразу вернет результат (если он уже посчитан) или заблокируется пока результата не будет." Работа с IAsyncResult примерно такая же (хотя есть дополнительные плюшки). Плюсы async/await как в упрощенном синтаксисе (код выглядит как синхронный), так и в отсутствии необходимости самому опрашивать возвращенный «специальный» объект на наличие результата. Ничего блокироваться не будет.
0
Это часть того, что называется в дотнете APM — asynchronous programming model. Классы, которые поддерживают асинхронное выполнение, должны следовать рекомендациям по их оформлению соответствующим образом. К примеру, если обычный метод назывался DoSomething, то его асинхронная версия должна быть парой методов BeginDoSomething/EndDoSomething. Begin-метод должен возвращать IAsyncResult, а End-метод принимать его в качестве аргумента.
А IAsyncResult вы можете реализовать как вы хотите (если вы делаете асинхронный API). Это не обязательно просто хранилище для хендла, в общем случае это объект, представляющий собой контекст выполняемой асинхронной операции.
А IAsyncResult вы можете реализовать как вы хотите (если вы делаете асинхронный API). Это не обязательно просто хранилище для хендла, в общем случае это объект, представляющий собой контекст выполняемой асинхронной операции.
0
>В С++11 появилась схожая штука: ::std::async.
ничего общего с асинками в C# 5
автор шарповых асинков уже работает над тем же самым для будущего C++
ничего общего с асинками в C# 5
автор шарповых асинков уже работает над тем же самым для будущего C++
+3
Да, мне уже объяснили.
Ох, «будущий С++». Саттер сказал, что еще года 3 книг по С++11-то не появится, так как мало опыта. Так что «будущий С++» будет лет через 10. Если будет, конечно…
Ох, «будущий С++». Саттер сказал, что еще года 3 книг по С++11-то не появится, так как мало опыта. Так что «будущий С++» будет лет через 10. Если будет, конечно…
0
>Саттер сказал, что еще года 3 книг по С++11-то не появится, так как мало опыта.
появятся, на GoingNative у кого-то на слайде были примерные даты по выходу новых изданий известных книг по Си++.
>Так что «будущий С++» будет лет через 10
Последнее время к Си++ снова возрастает внимание, а вместе с ним и финансовые вливания. Так что думаю что будущий Си++ не придётся ждать так долго.
А если хочется аналога шарповых асинков прямо сейчас, то можно с помощью небольшой магии с макросами сделать примерно тоже самое, все детали по асинкам разжованы в блогах майкрософтовцев.
появятся, на GoingNative у кого-то на слайде были примерные даты по выходу новых изданий известных книг по Си++.
>Так что «будущий С++» будет лет через 10
Последнее время к Си++ снова возрастает внимание, а вместе с ним и финансовые вливания. Так что думаю что будущий Си++ не придётся ждать так долго.
А если хочется аналога шарповых асинков прямо сейчас, то можно с помощью небольшой магии с макросами сделать примерно тоже самое, все детали по асинкам разжованы в блогах майкрософтовцев.
+1
Вы ведь смотрели GoingNative?
Там фраза и про стандарт была, что еще даже загадывать рано и сейчас основная проблема — библиотеки. Нужно хотя бы лет за 5 набрать объем сопоставимый с с# и java.
Про книги я оттуда же и взял: и серьезные книги (типа Exceptional C++ или Effective C++) это как раз через 3 года минимум.
Там фраза и про стандарт была, что еще даже загадывать рано и сейчас основная проблема — библиотеки. Нужно хотя бы лет за 5 набрать объем сопоставимый с с# и java.
Про книги я оттуда же и взял: и серьезные книги (типа Exceptional C++ или Effective C++) это как раз через 3 года минимум.
0
Он недавно писал что под «y» в новом стандарте C++1y они надеются что будет 7.
herbsutter.com/2012/03/08/trip-report-february-2012-c-standards-meeting/
herbsutter.com/2012/03/08/trip-report-february-2012-c-standards-meeting/
0
Выглядит действительно вкусно. Жаль, нескоро это появится у большинства пользователей. У многих не то что 4.5, даже 4.0 то не стоит )
+1
Windows 8 думаю с 4.5 выпустят, или только 4.0 там будет?
-1
А в чём проблема таскать фреймворк с собой?
+1
НЛО прилетело и опубликовало эту надпись здесь
Плюс ко всему можно даже не таскать с собой, а в инсталлере проверять его наличие, и грузить в процессе установки, при необходимости.
+1
Так и делаю. Проблема в том, что у некоторых юзеров возникают проблемы с установленным ранее .NET. Не работает программа, пока не переустановишь его с нуля. Правда, к наличию изначально у юзера .NET это отношения не имеет, согласен.
+1
А можно поподробнее?
0
Возникают совершенно безумные эксцепшны при инициализации главного окна программы.
Что то вроде:
Исключение 0: Инициализатор типа «System.Windows.Media.FontFamily» выдал исключение.
0: — Void System.Windows.Media.Typeface..ctor(System.Windows.Media.FontFamily, System.Windows.FontStyle, System.Windows.FontWeight, System.Windows.FontStretch)
0: — System.Windows.Media.Typeface MS.Internal.Text.DynamicPropertyReader.GetTypeface(System.Windows.DependencyObject)
0: — Void MS.Internal.Text.TextProperties.InitCommon(System.Windows.DependencyObject)
0: — Void MS.Internal.Text.TextProperties..ctor(System.Windows.FrameworkElement, Boolean)
…
с внутренним эксцепшном
Исключение 1: Исключение из HRESULT: 0xD000009C
0: — Void System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32, IntPtr)
0: — Void System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32, IntPtr)
0: — Void MS.Internal.Text.TextInterface.Native.Util.ConvertHresultToException(Int32)
0: — MS.Internal.Text.TextInterface.FontCollection MS.Internal.Text.TextInterface.Factory.GetSystemFontCollection(Boolean)
0: — MS.Internal.Text.TextInterface.FontCollection MS.Internal.FontCache.DWriteFactory.get_SystemFontCollection()
0: — Void System.Windows.Media.FontFamily..cctor()
или какой то компонент не находится. или просто пишет что не удалось проинициализировать программу корректно.
Использую .NET 4.0 и WPF
Что то вроде:
Исключение 0: Инициализатор типа «System.Windows.Media.FontFamily» выдал исключение.
0: — Void System.Windows.Media.Typeface..ctor(System.Windows.Media.FontFamily, System.Windows.FontStyle, System.Windows.FontWeight, System.Windows.FontStretch)
0: — System.Windows.Media.Typeface MS.Internal.Text.DynamicPropertyReader.GetTypeface(System.Windows.DependencyObject)
0: — Void MS.Internal.Text.TextProperties.InitCommon(System.Windows.DependencyObject)
0: — Void MS.Internal.Text.TextProperties..ctor(System.Windows.FrameworkElement, Boolean)
…
с внутренним эксцепшном
Исключение 1: Исключение из HRESULT: 0xD000009C
0: — Void System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32, IntPtr)
0: — Void System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32, IntPtr)
0: — Void MS.Internal.Text.TextInterface.Native.Util.ConvertHresultToException(Int32)
0: — MS.Internal.Text.TextInterface.FontCollection MS.Internal.Text.TextInterface.Factory.GetSystemFontCollection(Boolean)
0: — MS.Internal.Text.TextInterface.FontCollection MS.Internal.FontCache.DWriteFactory.get_SystemFontCollection()
0: — Void System.Windows.Media.FontFamily..cctor()
или какой то компонент не находится. или просто пишет что не удалось проинициализировать программу корректно.
Использую .NET 4.0 и WPF
0
Эксепшены всегда связаны со шрифтами?
0
Нее… Иногда не может найти System.Web, это я так понимаю если Compact Framework стоит. Иногда еще чего не может найти. Иногда в XAML ему что-то не нравится. В общем, странные эксцепшны.
0
BackgoundWorker можно закапывать?
-1
Ух ты, монада!
-9
Как только фоновый поток завершит работу и вернет результат — будет выполнено «продолжение» в основном потоке — могу сильно ошибаться, но вроде как это не всегда так. Т.е. «продолжение» может быть вызвано в совсем другом потоке нежели начало метода. Все зависит от того, как настроен текущий Dispatcher. В случае с WPF/Winforms приложений Dispatcher всегда вызывает код таски и ее продолжения в UI потоке. В общем случае это не так.
Кстати, это может привести к очень трудноуловимым багам. Представьте следующий код:
Да, он не очень логичен и даже не скомпилируется (внутри lock и catch await делать нельзя).
Беда в том, что многие текущие синхропримитивы привязаны к тому, что код внутри них выполняется в одном потоке, а с тасками это не всегда так.
Кстати, это может привести к очень трудноуловимым багам. Представьте следующий код:
lock(syncRoot)
{
await Download();
}
Да, он не очень логичен и даже не скомпилируется (внутри lock и catch await делать нельзя).
Беда в том, что многие текущие синхропримитивы привязаны к тому, что код внутри них выполняется в одном потоке, а с тасками это не всегда так.
+1
Совершенно верно, все зависит от текущего диспатчера. Вообще не вижу особого смысла применять эту технику для не UI потока, если только ради более красивой обработки исключений )
+1
Для не UI потока это точно так же полезно, поскольку код становится проще и понятней. Попробуйте переписать любым другим образом код, который будет содержать 3-4 вызова await. Там такая каша получится, будь здоров.
Еще один плюс await-ов в том, что они делают один лексический скоуп, что позволяет пользоваться такими вещами, как using, try/finally и т.д.
Т.е. это не просто более красивый код обработки исключений, эти штуки дают более читабельный код, который можно спокойно читать без боязни заработать непоправимые заболевания от вывиха извилин.
Еще один плюс await-ов в том, что они делают один лексический скоуп, что позволяет пользоваться такими вещами, как using, try/finally и т.д.
Т.е. это не просто более красивый код обработки исключений, эти штуки дают более читабельный код, который можно спокойно читать без боязни заработать непоправимые заболевания от вывиха извилин.
+6
Мне несколько раз приходилось писать туже самую state машину, что генерируется await'ами, но на ManualResetEvent'ах — выглядело ужасно. С await'ами же все это укладывается в несколько строчек.
+1
Встречайте, FCC :D
А unwind-protect не асилили. Слабаки
А unwind-protect не асилили. Слабаки
-5
Красиво и понятно. Спасибо за объяснение. Жду с нетерпением!
+1
Когда сложное объясняется просто :) Спасибо!
0
А await коллекции возможен? Например, запустить обсчет AI четырех персонажей (соответственно в четырех потоках), а когда все расчеты закончатся — что-то продолжить делать.
-1
В общем виде это будет выглядеть как-то так:
Вот здесь в видео примерах есть применение WhenAll
List<Person> persons;
...
await TaskEx.WhenAll(from p in persons select p.ProcessAsync());
...
продолжение
Вот здесь в видео примерах есть применение WhenAll
0
— забегая вперед стоит сказать, что await умеет работать только с функциями возвращающими Task и Task.
Ты ошибаешься. await будет работать с любым типом, имеющим метод(или экстеншн метод) GetAwaiter()
Ну короче тоже самое, как и foreach, которому совсем не нужен IEnumerable. Достаточно того, чтоб тип имел метод GetEnumerator. Или как query syntax в линке. Реализуй для int'а экстеншн методы Select/Where/SelectMany и пиши спокойно:
var _ = from x in 10
from y in 20
where y > 15
select x + y;
Ты ошибаешься. await будет работать с любым типом, имеющим метод(или экстеншн метод) GetAwaiter()
Ну короче тоже самое, как и foreach, которому совсем не нужен IEnumerable. Достаточно того, чтоб тип имел метод GetEnumerator. Или как query syntax в линке. Реализуй для int'а экстеншн методы Select/Where/SelectMany и пиши спокойно:
var _ = from x in 10
from y in 20
where y > 15
select x + y;
0
с таким косяком «особенностью» в Exception Handling — этот концепт становится алогичным и неприменимым.
0
Именно поэтому методы имеющие в теле await отмечаются как async. Нужно просто правильно использовать технологию… асинхронность как ни круто будет накладывать ограничения. Новый синтаксис сильно сокращает количество инфраструктурного кода + облегчает обработку исключений, но нельзя же ждать чтобы код вел себя совсем уж как синхронный
0
Task<string> task = new WebClient().DownloadStringTaskAsync("http://microsoft.com/");
task.Wait(); // Здесь мы ждем завершения задачи, что блокирует поток
TextBox.Text = task.Result;
Конечно, посту уже 100 лет. Но вот что-то мне кажется, что Вы не проверяли это.
Такая штука работать не будет)
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
C# 5 — об async/await с начала