какая разница между task.whenAll и configurewait? - PullRequest
0 голосов
/ 08 июня 2018

У меня есть асинхронный метод, который получает данные из базы данных:

private async Task getDataAsync()
{
    await getDataFromDatabaseAsync();
}

У меня есть конструктор, который использует этот метод следующим образом:

public MyViewModel()
{
    Task.WhenAll(getDataAsync());
    //getDataAsync().ConfigureAwait(false);

    //next line of code
}

Единственный способ, которымЯ стараюсь избежать того, чтобы приложения не блокировались, используя один из двух вариантов, оба, кажется, работают нормально.Я могу использовать WhenAll или ConfigureAwait (false).

Другие варианты - вызов метода getDataASync () внутри задачи, но я полагаю, что это худший вариант, поскольку он требует больше ресурсов.

Итак, я хотел бы знать, в чем различия между WhenAll и ConfigureAwait.

Когда я так использую WhenAll, строка кода «следующая строка кода» запускается после завершения асинхронного методаили он запустится до финиша?

Спасибо.

1 Ответ

0 голосов
/ 08 июня 2018

Существует распространенное заблуждение, что когда вы создаете метод async, он будет фактически выполняться асинхронно (то есть в отдельном потоке).Это не так: async и await являются средством синхронизации уже асинхронного кода.Если у вас нет ничего, что выполняется в отдельном потоке, ваш код async будет выполняться полностью синхронно до конца.

Поскольку getDataAsync выполняется в том же потоке, что и конструктор MyViewModel, вы можетезайти в тупик, так как поток ждет себя.Когда вы используете ConfigureAwait, вы можете избежать этой ситуации.

Если вы действительно должны сделать, это другой вопрос.Что вы на самом деле делаете с ConfigureAwait, так это запускаете задачу и позволяете ожидать продолжения в отдельном контексте (который может быть в отдельном потоке).Помимо того, что вы даже не используете await здесь, продолжение в другом контексте может стать проблемой, если вы хотите выполнить операции пользовательского интерфейса после ожидания.

Если вы хотите быть уверены, что можетедождитесь getDataAsync в вашем конструкторе, вы можете использовать Task.Run для принудительного выполнения в пуле потоков:

var getDataTask = Task.Run((Func<Task>)getDataAsync);
//Do something else
getDataTask.Wait();

Все, что вы выполняете между Task.Run и Wait(), может выполняться во время выполненияgetDataAsync.То, стоит ли здесь на самом деле параллелизм, зависит от того, что вы будете делать до тех пор, пока Wait().

То, что вы делаете в конструкторе MyViewModel, - это окончательная синхронизация всех асинхронных операций и синхронное выполнение конструктора.,Если вы хотите выполнить эту операцию асинхронно, вам потребуется запустить другую задачу , чтобы сделать это.Таким образом, вы должны быть действительно уверены, что после этого пункта async больше не требуется.Если это так, запустите инициализацию для другого метода async, await getDataAsync() там и синхронизируйте где-нибудь по цепочке вызовов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...