Дождаться окончания асинхронной задачи - PullRequest
1 голос
/ 16 апреля 2020

У меня есть задача, которая выполняется асинхронно, и сразу после этого у меня есть второй метод, который должен получить информацию из асинхронной задачи. Я не могу изменить асинхронную задачу, поэтому я хотел узнать, можно ли сказать второму методу, чтобы он дождался завершения асинхронного метода.

foreach (AgentModel ag in Agents)
{
    if (ag.IsEnabledRow == true)
    {
        if (ag.IsSelected == true)
        {
            if (ag.selectedMatrice != null)
            {
                if (ag.selectedWeeks != null)
                {
                    //on vérifie le cycle choisi et on adapte la date en conséquence
                    semaineAAppliquer(ag);

                    ag.IsEnabledRow = false;

                    Task<int> attribuerPlanning = Gestion.AttrPlanning(
                        _dataService.ParamGlobaux.IDEtablissement,
                        _dataService.ParamGlobaux.Matricule,
                        _dataService.ParamGlobaux.ConnectionString,
                        ag.Matricule, ag.selectedMatrice.IDMatrice, DsCalendrierCongés,
                        dateDebutCycle, ag.dateFin, HoraireAZero, CompleterPriseVide,
                        RemplacerRH, JFRepos,
                        (text, title, buttons) => System.Windows.MessageBox.Show(
                            text, title, buttons), _progress, DecalageSemaine,
                            appliquerCouleur, _ToutEtablissement);
                }
            }
            else
            {
                System.Windows.MessageBox.Show($"Sélectionner une matrice pour" +
                    $" l'agent {ag.Nom}.");
            }
        }
    }
}

UpdateListeContrats();

Метод attribuerPlanning - это асинхронный метод, и я бы хотел, не изменяя сам метод, чтобы он заканчивался перед вызовом UpdateListeContrats.

Или, как способ сказать UpdateListeContrats, не запускайте себя, пока другой метод не будет завершен.

(В настоящее время updateListeContrats запускается без обновления информации методом attributerPlanning.)

Ответы [ 2 ]

5 голосов
/ 16 апреля 2020

Во-первых, вам практически никогда не следует «ждать» (синхронно) выполнения задачи, но хорошо «ждать» ее (асинхронно).

В этом случае наиболее подходящий место для этого, вероятно, находится: на сайте вызова, т.е.

if (ag.selectedWeeks != null)
{
    //on vérifie le cycle choisi et on adapte la date en conséquence
    semaineAAppliquer(ag);

    ag.IsEnabledRow = false;

    var result = await Gestion.AttrPlanning( ... );
}

В дополнение к простоте, это также позволяет избежать проблем параллелизма; большая часть кода не ожидает одновременного использования в одном и том же контексте.

В общем случае вы можете захватить задачу (и т.д. c) в одном месте и ждать ее позже, но в вашем случае возникает проблема, что делать с foreach / if и т. д .; таких задач может быть ноль, одна или много, если вы выполняете их одновременно. Но я думаю, вы могли бы бросить их в список, то есть

var pending = new List<Task<int>>();
// ...
            pending.Add(attribuerPlanning);
// ...
var results = await Task.WhenAll(pending);
0 голосов
/ 16 апреля 2020

ОБНОВЛЕНИЕ: Как указал Мар c, не делайте этого, если у вас есть что-то, что не должно или не должно блокироваться в главном потоке, например GUI.

Вы можете сделать attribuerPlanning.Wait(); после вызова.

Или, если вы хотите запустить все задачи в foreyn asyn c и подождать, пока все задачи завершатся sh до UpdateListeContrats, вы можете создайте список задач вне foreach:

List<Task> tasks = new List<Task>();

и в теле l oop добавьте текущую задачу в список:

var task = Task.Run(() => Gestion.AttrPlanning(...) );
tasks.Add(task);

и вне foreach сделайте

Task.WhenAll(tasks).Wait();
UpdateListeContrats();
...