web-dev-qa-db-fra.com

Attendre asynchrone / attendre dans une tâche

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?

44
Nathan Cooper

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

90
i3arnon

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.

5
Nathan Cooper

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.

1
Siddharth Shakya