Это нормально, если RunAsync никогда не ожидался?
Это зависит. Это нормально с точки зрения JoinableTaskFactory
. Все необходимые продолжения будут продолжены - просто ваш вызывающий метод не будет ждать его завершения, и в этом весь смысл не ожидать его, если вы решите это сделать.
Но в целом, это может быть вредно для вашего приложения. Рассмотрим случай, когда ваша асинхронная работа сохраняет файл (или передает что-то по сети), и пользователь закрывает ваше приложение. Разве вы не хотите, чтобы приложение дождалось его завершения перед закрытием? Как сказал @GrzegorzSmulko в своем ответе, JoinableTaskFactory
предписывает шаблон для блокировки при отключении (или утилизации вашего объекта) для обеспечения завершения асинхронной работы.
Есть еще одна причина для отслеживания асинхронной работы, если вы находитесь в приложении, в котором размещается CLR и отключается перед выходом: вы не хотите, чтобы управляемые потоки выполняли произвольные действия, когда завершается финализация AppDomain или вы ' Вы увидите, что ваше приложение зависает при завершении работы. Это не проблема, если у вас есть чисто управляемое приложение, поскольку оно просто завершает работу, не выключая CLR. Он не рухнет, но все равно откажется от любой полуработы.
Все вышесказанное верно для любого приложения, для которого вы используете JoinableTaskFactory
. Если вы используете его в Visual Studio (я говорю здесь в целом для более широкой аудитории ... Я знаю ваш вопрос, конкретно упомянул VS), тогда правила будут подчеркнуты больше. Вы должны отслеживать все свою асинхронную работу, как предписано в этом разделе. У вас не должно быть никакой работы «огонь и забудь».
Метод расширения FileAndForget
фактически предназначен для внутреннего использования корпорацией Майкрософт, поскольку он отправляет ошибки на наши серверы телеметрии. Если вы действительно хотите просто забыть что-то, вы можете использовать метод расширения .Forget()
. Но помните, что вы должны использовать это только после планирования работы с использованием экземпляра AsyncPackage.JoinableTaskFactory
или другого, который отслеживает вашу асинхронную работу для удаления. Не используйте его на ThreadHelper.JoinableTaskFactory
, потому что это не отслеживает асинхронную и забытую работу. Так, например, не сделать это:
ThreadHelper.JoinableTaskFactory.RunAsync(async () => { /* something async */ }).Forget();
Проблема с вышесказанным заключается в том, что асинхронная работа не будет отслеживаться и, следовательно, не блокировать отключение. Вы должны сделать это вместо:
myAsyncPackage.JoinableTaskFactory.RunAsync(async () => { /* something async */ }).Forget();
Или даже лучше: просто ожидайте вызова, и в этом случае вы можете использовать практически любой экземпляр JTF:
await ThreadHelper.JoinableTaskFactory.RunAsync (async () => {/ * что-то async * /});