Информация об изменениях

Сообщение Re: SemaphoreSlim(1, 1) WaitAsync 2 -- пару вопросов. от 30.12.2020 8:06

Изменено 30.12.2020 8:18 Serginio1

Re: SemaphoreSlim(1, 1) WaitAsync 2 -- пару вопросов.
Здравствуйте, Sharov, Вы писали:

Избегайте async void

Очевидно, что async void-методы имеют ряд недостатков по сравнению с async Task-методами, но они весьма полезны в одном конкретном случае: использовании в качестве асинхронных обработчиков событий. Различия в семантике имеют смысл для таких обработчиков. Они генерируют свои исключения непосредственно в SynchronizationContext, т. е. ведут себя так же, как синхронные обработчики событий. Синхронные обработчики обычно являются закрытыми, поэтому они не подлежат композиции и их нельзя тестировать напрямую. Я предпочитаю такой подход: минимизация кода в асинхронных обработчиках событий, например пусть он ждет на async Task-методе, содержащем реальную логику


Async void-методы могут посеять хаос, если вызвавший код не ожидает, что они окажутся асинхронными. Когда возвращается тип Task, вызвавший код знает, что имеет дело с операцией future, а когда возвращаемый тип — void, вызвавший код может предположить, что метод завершается к моменту возврата им управления. У этой проблемы может быть множество неожиданных проявлений. Обычно неправильно предоставлять async-реализацию (или переопределение) void-метода какого-либо интерфейса (или базового класса). Некоторые события также предполагают, что их обработчики завершаются, когда они возвращают управление. Еще одна тонкая ловушка — передача асинхронной лямбды в метод, принимающий параметр Action; в этом случае async-лямбда возвращает void и наследует все проблемы async void-методов. Как общее правило, async-лямбды следует использовать, только если они преобразуются в тип делегата, который возвращает Task (например, Func<Task>).

Re: SemaphoreSlim(1, 1) WaitAsync 2 -- пару вопросов.
Здравствуйте, Sharov, Вы писали:

Избегайте async void

Очевидно, что async void-методы имеют ряд недостатков по сравнению с async Task-методами, но они весьма полезны в одном конкретном случае: использовании в качестве асинхронных обработчиков событий. Различия в семантике имеют смысл для таких обработчиков. Они генерируют свои исключения непосредственно в SynchronizationContext, т. е. ведут себя так же, как синхронные обработчики событий. Синхронные обработчики обычно являются закрытыми, поэтому они не подлежат композиции и их нельзя тестировать напрямую. Я предпочитаю такой подход: минимизация кода в асинхронных обработчиках событий, например пусть он ждет на async Task-методе, содержащем реальную логику


Async void-методы могут посеять хаос, если вызвавший код не ожидает, что они окажутся асинхронными. Когда возвращается тип Task, вызвавший код знает, что имеет дело с операцией future, а когда возвращаемый тип — void, вызвавший код может предположить, что метод завершается к моменту возврата им управления. У этой проблемы может быть множество неожиданных проявлений. Обычно неправильно предоставлять async-реализацию (или переопределение) void-метода какого-либо интерфейса (или базового класса). Некоторые события также предполагают, что их обработчики завершаются, когда они возвращают управление. Еще одна тонкая ловушка — передача асинхронной лямбды в метод, принимающий параметр Action; в этом случае async-лямбда возвращает void и наследует все проблемы async void-методов. Как общее правило, async-лямбды следует использовать, только если они преобразуются в тип делегата, который возвращает Task (например, Func<Task>).


Ну и как в той ветке проверить обшее количество выполненных add remove