Начну с бенчмарков: их нет, и это честно. Чтобы сделать показательный тест, нужен целый проект, а на это уйдёт время. Если вам интересно — можете сами прогнать, я буду только рад увидеть цифры. Но суть не в скорости, а в управляемости: события толкают данные сами, а IAsyncEnumerable позволяет тебе решать, когда их брать. Это не «быстрее», это «удобнее» для сложных сценариев.
По поводу UI — вы правы, в конечном счёте всё упирается в UI. Но разница в том, кто задаёт темп: события могут захлебнуться, если данные летят быстрее, чем ты успеваешь их обрабатывать — и тогда приходится буферизировать вручную, что ведёт к росту памяти и нагрузке на GC. IAsyncEnumerable даёт контроль: хочешь — обрабатывай быстро, хочешь — поставь паузу.
«Полное соответствие чистой архитектуре» — громко сказано, согласен. В примере из статьи я использую прямое создание экземпляра FindDevicesService, чтобы не усложнять код и сфокусироваться на IAsyncEnumerable. В реальных проектах я использую DI и интерфейсы, но в статье это опущено, чтобы не отвлекать. Суть подхода — не в интерфейсах, а в управляемом потоке данных, отменяемости и линейном коде без Dispatcher.Invoke.
«Контроль над потоком» — это про возможность остановить, притормозить, отменить или перераспределить данные. События так не умеют: ты подписался — и данные летят сами, независимо от твоей готовности.
Статья не претендует на истину в последней инстанции. Это мой практический опыт, как уйти от Dispatcher.Invoke и событийного ада. Если есть конкретные сценарии, где этот подход не работает — буду рад обсудить. А с бенчмарками вы правы — было бы круто их добавить, но это уже за рамками формата.
Спасибо за вопросы — они по делу.
Начну с бенчмарков: их нет, и это честно. Чтобы сделать показательный тест, нужен целый проект, а на это уйдёт время. Если вам интересно — можете сами прогнать, я буду только рад увидеть цифры. Но суть не в скорости, а в управляемости: события толкают данные сами, а IAsyncEnumerable позволяет тебе решать, когда их брать. Это не «быстрее», это «удобнее» для сложных сценариев.
По поводу UI — вы правы, в конечном счёте всё упирается в UI. Но разница в том, кто задаёт темп: события могут захлебнуться, если данные летят быстрее, чем ты успеваешь их обрабатывать — и тогда приходится буферизировать вручную, что ведёт к росту памяти и нагрузке на GC. IAsyncEnumerable даёт контроль: хочешь — обрабатывай быстро, хочешь — поставь паузу.
«Полное соответствие чистой архитектуре» — громко сказано, согласен. В примере из статьи я использую прямое создание экземпляра FindDevicesService, чтобы не усложнять код и сфокусироваться на IAsyncEnumerable. В реальных проектах я использую DI и интерфейсы, но в статье это опущено, чтобы не отвлекать. Суть подхода — не в интерфейсах, а в управляемом потоке данных, отменяемости и линейном коде без Dispatcher.Invoke.
«Контроль над потоком» — это про возможность остановить, притормозить, отменить или перераспределить данные. События так не умеют: ты подписался — и данные летят сами, независимо от твоей готовности.
Статья не претендует на истину в последней инстанции. Это мой практический опыт, как уйти от Dispatcher.Invoke и событийного ада. Если есть конкретные сценарии, где этот подход не работает — буду рад обсудить. А с бенчмарками вы правы — было бы круто их добавить, но это уже за рамками формата.