Но мой вопрос заключается в том, есть ли способ узнать статус задачи, используя сохраненный идентификатор
№. Учитывая идентификатор, вы не можете найти объект Task
. Вам нужно будет хранить их самостоятельно в потокобезопасном словаре, таком как ConcurrentDictionary
, и не забудьте удалить их из словаря по завершении, иначе вы получите утечку ресурсов.
Например, я вызываю API с долго выполняющейся задачей, API вызывает Task.Run, и поскольку он асинхронный, я возвращаю 202.
Это чрезвычайно опасное решение. Есть несколько проблем с ним:
- Поскольку работа полностью находится в памяти (в рабочей очереди пула потоков), работа теряется каждый раз при перезагрузке сервера, перезапуске хост-приложения или перезапуске пула приложений. Два распространенных сценария: развертывание обновления кода или применение исправления ОС; любой из них может привести к потере работы.
- Поскольку поиск идентификатора в статусе также выполняется в памяти, любые вызовы API для проверки состояния должны попадать в тот же экземпляр, что и вызов API, который начал работу. В фермах серверов это обычно не так.
Как этого добиться.
Единственным реальным решением для асинхронного обмена сообщениями является базовая распределенная архитектура:
- Надежная очередь, т.е. не в памяти.
- Внутренняя служба для обработки очереди. Этот может размещаться в том же приложении, что и веб-служба, но обычно я рекомендую сделать его независимым процессом.
- Система отслеживания/получения результатов. Это может быть устойчиво или в некоторой (распределенной) памяти, такой как Redis.
Но на этот раз это не асинхронность, не так ли? Так почему везде говорят добавить Await перед вызовом task.run
Это потому, что здесь есть два разных значения слова "асинхронный". «Асинхронный» может означать «отдать текущий поток». Это также может означать что-то другое на более высоком уровне; в этом случае это может означать «вызов API для запуска операции» — обычно это называется «асинхронный обмен сообщениями».
При использовании ключевых слов async
/await
в ASP.NET они являются "асинхронными" в том смысле, что они позволяют потоку запроса возвращаться в пул потоков. Они не являются "асинхронными" в том смысле, что возвращаются клиенту рано.
Пожалуйста, позвольте мне поделиться своей идеей здесь. Во-первых, я не уверен, можно ли проверять статус потока между потоками. Если это не поддерживается, вы можете проверить результат выполнения потока. Например. вернуть идентификатор задачи при вызове первого API. И отправьте идентификатор задачи в качестве параметра второго API. При завершении первой задачи API вы можете сохранить результат задачи в одной таблице с идентификатором задачи в строке. И вызов второго API для запроса этой таблицы, чтобы проверить, завершена ли эта задача.