Как правильно использовать JoinableTaskFactory.RunAsync? - PullRequest
0 голосов
/ 01 мая 2018

Я искал в Интернете, но информации о ThreadHelper.JoinableTaskFactory.RunAsync

очень мало

Если у меня есть следующий код, Test1 работает на MainThread:

public bool Test1()
{
    // Do something here
    ThreadHelper.JoinableTaskFactory.RunAsync(this.Test2);
    // Do something else
    return false;
}

private async Task Test2()
{
    await TaskScheduler.Default;
    // do something here    
    await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
    // do something here
}

Это нормально, если RunAsync никогда не ожидали? Что произойдет, если Test1 вернется до того, как Test2 завершит работу?

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Это нормально, если 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 * /});

0 голосов
/ 01 мая 2018

Согласно Threading Cookbook для Visual Studio вы должны использовать ThreadHelper.JoinableTaskFactory.RunAsync() вместе с FileAndForget().

Потенциальная проблема в том, что FileAndForget() недоступен в VS2015, но только в VS2017 +.

Это нормально, если RunAsync никогда не ожидали?

Я думаю, что это не хорошо, вы должны использовать FileAndForget. Но я не знаю, что делать с VS2015.

Что произойдет, если Test1 вернется до того, как Test2 завершит работу?

Это должно быть довольно легко проверить, чтобы убедиться. Я предполагаю, что Test2 только что закончится позже "Но вы также должны быть уверены, что ваша асинхронная работа завершится до того, как ваш объект заявит о своем распоряжении."

...