#ЗаметкиНаПолях #AsyncTips**
Передача информации о ходе выполнения операции
Задача: отреагировать на прогресс выполнения операции.
Решение:
**Используйте
```IProgress<T>```
и
```Progress<T>```
. Ваш асинхронный метод должен получать аргумент
```IProgress<T>```
; здесь
```T```
— тип прогресса, о котором вы хотите сообщать:
```async Task MyMethodAsync(IProgress<double> progress = null)
{
bool done = false;
double completed = 0;
while (!done) {
...
progress?.Report(completed);
}
}
Пример использования в вызывающем коде:
```async Task CallMyMethodAsync()
{
var progress = new Progress<double>(
p => progressBar.Value = p
);
await MyMethodAsync(progress);
}
По действующим соглашениям параметр
```IProgress<T>```
может быть равен
```null```
, если вызывающей стороне не нужны уведомления о прогрессе. Включите соответствующую проверку в асинхронный метод.
Лучше определить
```T```
как неизменяемый тип (или тип-значение). Если
```T```
является изменяемым ссылочным типом, то вам придётся самостоятельно создавать отдельную копию при каждом вызове
```IProgress<T>.Report```
.
```Progress<T>```
сохраняет текущий контекст при создании и активизирует свой обратный вызов в этом контексте. Это означает, что если
```Progress<T>```
конструируется в UI-потоке (как в методе
```CallMyMethodAsync```
выше), то вы сможете обновить пользовательский интерфейс из его обратного вызова, даже если асинхронный метод вызывает
```Report```
из фонового потока.
Заметьте, что, если метод поддерживает уведомления о прогрессе, лучше, чтоб он также поддерживал отмену.
Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 2.