Reputation: 69
I have a task that runs asynchronously, and I have a second method, right after that, that needs to retrieve the information from the asynchronous task. I can't modify the asynchronous task, so I wanted to know if it's possible to tell the second method to wait until the asynchronous method is finished.
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();
The attribuerPlanning
method is the asynchronous method, and I would like, without modifying the method itself, that it ends before calling UpdateListeContrats
.
Or a way of saying UpdateListeContrats
, don't trigger yourself until the other method is complete.
(Currently, updateListeContrats
launches without having the information updated by the attributerPlanning
method.)
Upvotes: 1
Views: 261
Reputation: 1611
UPDATE: As Marc pointed out, don't do this if you have something that shouldn't or mustn't be blocked in the main thread, like a GUI.
You can do attribuerPlanning.Wait();
after calling it.
Or if you want to run all task in the foreach async and wait all task to finish before UpdateListeContrats you can create a task list outside of the foreach:
List<Task> tasks = new List<Task>();
and in the loop body add the current task to the list:
var task = Task.Run(() => Gestion.AttrPlanning(...) );
tasks.Add(task);
and outside of foreach do
Task.WhenAll(tasks).Wait();
UpdateListeContrats();
Upvotes: -1
Reputation: 1062492
Firstly, you should virtually never "wait" (synchronous) for a task, but it is fine to "await" it (asynchronous).
In this case, the most appropriate place to do this is probably: at the call site, i.e.
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( ... );
}
In addition to being simple, this also avoids concurrency issues; most code is not anticipating concurrent usage in the same context.
In the general case, you can capture the task (etc) at one place, and await it later, but in your case the problem becomes what to do about the foreach
/if
etc; there could be zero, one, or many such tasks, if you are running them concurrently. But I guess you could throw them in a list, i.e.
var pending = new List<Task<int>>();
// ...
pending.Add(attribuerPlanning);
// ...
var results = await Task.WhenAll(pending);
Upvotes: 5