Как я могу ждать, чтобы void async
метод закончил свою работу?
например, у меня есть функция, как показано ниже:
async void LoadBlahBlah()
{
await blah();
...
}
Теперь я хочу убедиться, что все загружено, прежде чем продолжить в другом месте.
c#
asynchronous
MBZ
источник
источник
await Task.Run(() => An_async_void_method_I_can_not_modify_now())
await Task.Run(() => blah())
вводит в заблуждение. Это не ожидает завершения асинхронной функцииblah
, оно просто ожидает (тривиального) создания задачи и продолжается непосредственно передblah()
ее завершением.Thread.Sleep
не асинхронно. Этот вопрос о ожиданииasync void
функции, скажемasync void blah() { Task.Delay(10000); }
Если вы можете изменить сигнатуру своей функции на,
async Task
то вы можете использовать код, представленный здесьисточник
Лучшее решение - использовать
async Task
. Вам следует избегатьasync void
по нескольким причинам, одной из которых является составность.Если метод не может быть выполнен для возврата
Task
(например, это обработчик события), то вы можете использоватьSemaphoreSlim
для получения сигнала метода, когда он собирается выйти. Подумайте об этом вfinally
блоке.источник
сделать AutoResetEvent, вызвать функцию, затем подождать AutoResetEvent и затем установить его в async void, когда вы знаете, что это сделано.
Вы также можете подождать выполнения задачи, которая возвращается из вашей асинхронной пустоты.
источник
Вам не нужно ничего делать вручную,
await
ключевое слово приостанавливает выполнение функции до тех пор, пока неblah()
вернется.T
типblah()
возвращаемого объектаВы не можете действительно функция так не может быть
await
void
LoadBlahBlah()
void
источник
LoadBlahBlah()
окончания, а неblah()
Я знаю, что это старый вопрос, но я все еще сталкиваюсь с этой проблемой, и все же нет четкого решения, как правильно сделать это при использовании async / await в методе асинхронной подписи void.
Однако я заметил, что .Wait () работает правильно внутри метода void.
и поскольку async void и void имеют одну и ту же подпись, вам может потребоваться сделать следующее.
Достаточно запутанно async / await не блокирует следующий код.
Когда вы декомпилируете свой код, я предполагаю, что async void создает внутреннюю задачу (так же, как async Task), но поскольку подпись не поддерживает возврат этой внутренней задачи
это означает, что внутренне асинхронный метод void все еще сможет "ожидать" внутренне асинхронных методов. но внешне не может знать, когда внутренняя задача завершена.
Таким образом, я пришел к выводу, что async void работает как задумано, и если вам нужна обратная связь от внутренней Задачи, вам нужно вместо этого использовать подпись асинхронной Задачи.
надеюсь, моя болтовня имеет смысл для всех, кто также ищет ответы.
Изменить: я сделал пример кода и декомпилировал его, чтобы увидеть, что на самом деле происходит.
Превращается в (править: я знаю, что код тела не здесь, а в машинах состояний, но машины состояний были в основном идентичны, поэтому я не стал добавлять их)
ни AsyncVoidMethodBuilder, ни AsyncTaskMethodBuilder на самом деле не имеют никакого кода в методе Start, который бы намекал на их блокировку, и всегда запускался бы асинхронно после их запуска.
То есть без возврата Задачи не было бы способа проверить, завершена ли она.
как и ожидалось, он только запускает задачу, выполняющую асинхронную работу, а затем продолжает работу в коде. и асинхронная задача, сначала она запускает задачу, а затем возвращает ее.
поэтому я думаю, что мой ответ будет состоять в том, чтобы никогда не использовать async void, если вам нужно знать, когда задача выполнена, для этого и предназначена асинхронная задача.
источник