Коллега пытался выяснить, почему его обработчик прогресса не вызывается.
Это довольно стандартная ситуация. Запускаешь операцию, подключаешь обработчик прогресса и затем ждёшь завершения операции. Но прогресса они так и не видели.
Я попросил проверить, не скачивается ли элемент настолько быстро, что они пропускают все события прогресса. Но нет — даже если загрузка идёт долго, никакого прогресса не появляется.
Я предложил пройти пошагово через метод DownloadAsync, чтобы увидеть, где он генерирует события прогресса, а затем проследить выполнение до места, где должен вызываться callback прогресса, чтобы понять, почему этого не произошло. (Честно говоря, это задача отладки через языковой барьер, поэтому она сложнее, чем кажется. Я предложил сосредоточиться только на стороне C++: дождаться, когда будет сгенерирован COM-callable wrapper и установлен как callback прогресса, а затем поставить брейкпоинт на этом wrapper. Если этот брейкпоинт срабатывает, а C# код не выполняется, значит проблема в проекции. Если брейкпоинт вообще не срабатывает, значит проблема на стороне C++.)
Мой коллега вернулся с ответом. Вот код DownloadAsync:
AggregateSource собирает элементы от нескольких провайдеров. Формат id — это provider, двоеточие и затем ID. (И provider ID, и item ID экранируются, на случай если в них самих окажется двоеточие.)
Мы находим провайдера, а затем просим провайдера скачать элемент.
DownloadAsync вовсе не генерирует отчёты о прогрессе!
Он никогда не вызывает co_await winrt::get_progress_token(), не говоря уже о вызове токена с значением прогресса, чтобы сгенерировать отчёт о прогрессе.
Становится очевидно, что код при подключении callback прогресса пытается получать обратные вызовы от внутренней операции, той, что возвращает провайдер. Однако единственный IAsyncOperationWithProgress, к которому у него есть доступ, — это тот, что возвращён методом AggregateSource::DownloadAsync.
Простое решение здесь — убрать посредника и просто возвращать IAsyncOperationWithProgress от провайдера. Тогда вызывающий код сможет подключиться к прогрессу внутренней операции.
Если вы не доверяете completed_async, можно просто написать
Я сказал, что это простое решение. Есть и сложное решение, но о нём придётся рассказывать позже, потому что я ещё не написал об этом.
Рэймонд участвует в эволюции Windows более 30 лет. В 2003 году он запустил веб‑сайт под названием The Old New Thing, который стал популярнее, чем он мог себе представить, что до сих пор вызывает у него нервозность. Сайт породил книгу с тем же названием (Addison Wesley, 2007). Иногда он появляется в Twitter-аккаунте Windows Dev Docs, чтобы рассказывать истории, не несущие полезной информации.
Обсуждение закрыто. Войдите в систему, чтобы редактировать/удалять существующие комментарии.
