Как разрешить выполнение асинхронной задачи в течение заданного количества секунд?

Поэтому я создал обработчик задач. Я хочу, чтобы он работал в течение некоторого заранее определенного гарантированного периода времени, затем я хочу сделать некоторые из своих вещей, и только тогда мне нужно, чтобы результат обработчика ожидался. Что-то вроде:

var th = TaskCreator();
th.awaitFor(5000);
//do some work
var result = await th;

Итак, как асинхронная задача может выполняться в течение заданного количества секунд?

Что такое var th? Это Task? Пожалуйста, напишите конкретные типы на StackOverflow. Мы не можем навести указатель мыши на var и увидеть тип переменной!

Theodor Zoulias 18.11.2022 11:43
[JS за 1 час] - 9. Асинхронный
[JS за 1 час] - 9. Асинхронный
JavaScript является однопоточным, то есть он может обрабатывать только одну задачу за раз. Для обработки длительных задач, таких как сетевые запросы,...
Топ-10 компаний-разработчиков PHP
Топ-10 компаний-разработчиков PHP
Если вы ищете надежных разработчиков PHP рядом с вами, вот список лучших компаний по разработке PHP.
Скраппинг поиска Apple App Store с помощью Python
Скраппинг поиска Apple App Store с помощью Python
📌Примечание: В этой статье я покажу вам, как скрапировать поиск Apple App Store и получить точно такой же результат, как на Apple iMac, потому что...
Редкие достижения на Github ✨
Редкие достижения на Github ✨
Редкая коллекция доступна в профиле на GitHub ✨
Подъем в javascript
Подъем в javascript
Hoisting - это поведение в JavaScript, при котором переменные и объявления функций автоматически "перемещаются" в верхнюю часть соответствующих...
Улучшение генерации файлов Angular
Улучшение генерации файлов Angular
Angular - это фреймворк. Вы можете создать практически любое приложение без использования сторонних библиотек.
0
1
83
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете использовать WhenAny (документы):

var th = TaskCreator();
await Task.WhenAny(Task.Delay(TimeSpan.FromSeconds(5)), th);
//do some work
var result = await th;

Это прекратит ожидание завершения любой из задач, а это означает, что вы можете затем выполнить свою другую работу и переждать th в конце, чтобы дождаться ее завершения (или просто получить результат, если он уже завершен).

Если ваш метод TaskCreator выполняет много синхронной работы, прежде чем перейти к асинхронному, вы можете сначала вызвать await Task.Yield(); (docs) внутри метода TaskCreator, прежде чем использовать приведенный выше код.

Это, вероятно, даст вам предупреждение на .NET 8.

Theodor Zoulias 18.11.2022 11:46

Предпочтительным механизмом здесь было бы реализовать отмену в вашем TaskCreator. Это дает множество преимуществ:

  • это позволяет работе в TaskCreator фактически прекратить работу, когда истек тайм-аут
  • это обеспечивает гибкость в отношении будущих причин отмены

Пример:

using var cs = new CancellationTokenSource();
cs.CancelAfter(TimeSpan.FromSeconds(5));
var result = await TaskCreator(cs.Token);

Где ваш TaskCreator предположительно будет выглядеть примерно так:

async Task<int> TaskCreator(CancellationToken cancellationToken)

И где вы на самом деле используете cancellationToken в TaskCreator, либо напрямую (обычно через .ThrowIfCancellationRequested() или .Register(...)), либо косвенно (передавая его нижестоящим ожидаемым API).

Ответ Марка идеален. Если вы не можете добавить отмену по какой-либо причине, вы можете использовать WaitAsync:

var th = TaskCreator();
var result = await th.WaitAsync(TimeSpan.FromSeconds(5));

WaitAsync похож на обычный WhenAny подход, но без утечки таймеров.

Обратите внимание, что и WaitAsync, и WhenAny не отменяют операцию; они просто отменяют (а) ожидание. Ответ Марка правильно отменит операцию.

Не совсем очевидно, что в случае, если timeout истекает до завершения задачи, Task.WaitAsync распространяет TimeoutException.

Theodor Zoulias 18.11.2022 20:17

Другие вопросы по теме