J'ai cette construction dans ma main()
, qui crée
var tasks = new List<Task>();
var t = Task.Factory.StartNew(
async () =>
{
Foo.Fim();
await Foo.DoBar();
});
//DoBar not completed
t.Wait();
//Foo.Fim() done, Foo.DoBar should be but isn't
Cependant, lorsque je .Wait
Pour t, il n'attendra pas que l'appel à DoBar()
se termine. Comment puis-je faire attendre réellement?
Il est déconseillé d'utiliser Task.Factory.StartNew
avec async-await
, vous devez utiliser Task.Run
au lieu:
var t = Task.Run(
async () =>
{
Foo.Fim();
await Foo.DoBar();
});
Le Task.Factory.StartNew
l'api a été construit avant Pattern asynchrone basé sur les tâches (TAP) et async-await
. Il renverra Task<Task>
parce que vous démarrez une tâche avec une expression lambda qui se trouve être asynchrone et renvoie donc une tâche. Unwrap
extraira la tâche interne, mais Task.Run
le fera implicitement pour vous.
Pour une comparaison plus approfondie, il y a toujours un article pertinent de Stephen Toub: Task.Run vs Task.Factory.StartNew
Il semble que j'obtienne la fonctionnalité souhaitée en Unwrap()
ing la tâche. Je ne suis pas sûr d'avoir compris le raisonnement derrière cela, mais je suppose que cela fonctionne.
var t = Task.Factory.StartNew(
async () =>
{
Foo.Fim();
await Foo.DoBar();
}).Unwrap();
edit: J'ai cherché la description de Unwrap()
: Creates a proxy Task that represents the asynchronous operation of a Task<Task<T>>
Je pensais que c'était traditionnellement la tâche, mais si j'ai besoin d'appeler unwrap, je suppose que c'est bien.
J'ai récemment rencontré un problème similaire et j'ai compris que tout ce que vous devez faire est que DoBar()
retourne une valeur et utilise .Result au lieu d'attendre.
var g = Task.Run(() => func(arg));
var val = g.Result;
Cela attendra que func
renvoie sa sortie et l'affecte à val.