Проверьте статус потока, который вызывает с помощью Task.Run

avatar
Sandeep Thomas
9 августа 2021 в 05:52
53
1
0

Я пытаюсь проверить статус асинхронных задач, которые выполняются в цикле.

Вот как выглядит мой код

for(i=0;i<10;i++)
{
    Task t=Task.Run(()=>MyLongRunningTask(params));
   /// Feeding Task.Id
}

Здесь я загружаю идентификатор задачи. Но мой вопрос: есть ли способ узнать статус задачи, используя сохраненный нами идентификатор

.

Например, я вызываю API с длительной задачей, API вызывает Task.Run и, поскольку он асинхронный, я возвращаю 202.

Из другого API я пытаюсь проверить статус записанных выше потоков в этом цикле.

Как этого добиться.

Кроме того, я немного запутался, почему это предупреждение добавить Await. Когда я добавляю await, он будет ждать завершения процесса и только тогда, когда процесс завершит возврат данных. Но на этот раз это не асинхронно, не так ли? Так почему везде говорят добавить Await перед вызовом task.run

Источник
Tiny Wang
9 августа 2021 в 08:21
0

Пожалуйста, позвольте мне поделиться своей идеей здесь. Во-первых, я не уверен, можно ли проверять статус потока между потоками. Если это не поддерживается, вы можете проверить результат выполнения потока. Например. вернуть идентификатор задачи при вызове первого API. И отправьте идентификатор задачи в качестве параметра второго API. При завершении первой задачи API вы можете сохранить результат задачи в одной таблице с идентификатором задачи в строке. И вызов второго API для запроса этой таблицы, чтобы проверить, завершена ли эта задача.

Ответы (1)

avatar
Stephen Cleary
10 августа 2021 в 00:18
2

Но мой вопрос заключается в том, есть ли способ узнать статус задачи, используя сохраненный идентификатор

№. Учитывая идентификатор, вы не можете найти объект Task. Вам нужно будет хранить их самостоятельно в потокобезопасном словаре, таком как ConcurrentDictionary, и не забудьте удалить их из словаря по завершении, иначе вы получите утечку ресурсов.

Например, я вызываю API с долго выполняющейся задачей, API вызывает Task.Run, и поскольку он асинхронный, я возвращаю 202.

Это чрезвычайно опасное решение. Есть несколько проблем с ним:

  1. Поскольку работа полностью находится в памяти (в рабочей очереди пула потоков), работа теряется каждый раз при перезагрузке сервера, перезапуске хост-приложения или перезапуске пула приложений. Два распространенных сценария: развертывание обновления кода или применение исправления ОС; любой из них может привести к потере работы.
  2. Поскольку поиск идентификатора в статусе также выполняется в памяти, любые вызовы API для проверки состояния должны попадать в тот же экземпляр, что и вызов API, который начал работу. В фермах серверов это обычно не так.

Как этого добиться.

Единственным реальным решением для асинхронного обмена сообщениями является базовая распределенная архитектура:

  1. Надежная очередь, т.е. не в памяти.
  2. Внутренняя служба для обработки очереди. Этот может размещаться в том же приложении, что и веб-служба, но обычно я рекомендую сделать его независимым процессом.
  3. Система отслеживания/получения результатов. Это может быть устойчиво или в некоторой (распределенной) памяти, такой как Redis.

Но на этот раз это не асинхронность, не так ли? Так почему везде говорят добавить Await перед вызовом task.run

Это потому, что здесь есть два разных значения слова "асинхронный". «Асинхронный» может означать «отдать текущий поток». Это также может означать что-то другое на более высоком уровне; в этом случае это может означать «вызов API для запуска операции» — обычно это называется «асинхронный обмен сообщениями».

При использовании ключевых слов async/await в ASP.NET они являются "асинхронными" в том смысле, что они позволяют потоку запроса возвращаться в пул потоков. Они не являются "асинхронными" в том смысле, что возвращаются клиенту рано.