attendent vs Tâche.Wait - Impasse?

Je ne comprends pas très bien la différence entre Task.Wait et await.

J'ai quelque chose de similaire pour les fonctions suivantes dans un ASP.NET WebAPI service:

public class TestController : ApiController
{
    public static async Task<string> Foo()
    {
        await Task.Delay(1).ConfigureAwait(false);
        return "";
    }

    public async static Task<string> Bar()
    {
        return await Foo();
    }

    public async static Task<string> Ros()
    {
        return await Bar();
    }

    //GET api/test
    public IEnumerable<string> Get()
    {
        Task.WaitAll(Enumerable.Range(0, 10).Select(x => Ros()).ToArray());

        return new string[] { "value1", "value2" }; //This will never execute
    }
}

Get va se bloquer.

Ce qui a pu provoquer cela? Pourquoi n'est-il pas poser un problème lorsque j'utilise un blocage attendre plutôt que d' await Task.Delay?

  • Votre code est ne compile pas; votre méthode sont répertoriées comme ayant à la fois void et Task comme type de retour. Veuillez fournir compilable code qui illustre le problème. Oh, et quand j'ai corrigé cette erreur et exécuter le code que j'ai de ne pas faire l'impasse (qui je devrait être le cas).
  • Je vais revenir avec une pension dès que j'ai le temps. Pour le moment, il fonctionne avec Task.Delay(1).Wait() qui est assez bon.
  • Task.Delay(1).Wait() est fondamentalement la même chose que Thread.Sleep(1000). En production réelle de code, il est rarement approprié.
  • Ajoutée résultant de pensions de l'échantillon.
  • Votre WaitAll est à l'origine du blocage. Voir le lien vers mon blog dans ma réponse pour plus de détails. Vous devez utiliser await Task.WhenAll à la place.
  • Votre code est verrouillé parce que vous êtes de blocage sur les résultats d'une opération asynchrone, tout comme le lien de Stephen la réponse de la montre. Vous devez await tout le chemin jusqu'pour que cela fonctionne. De même, vous pouvez bloquer tous le chemin vers le bas et il va fonctionner. Dans votre exemple, où vous bloquez vous en fait jamais réellement await, vous bloquez tout le chemin, afin de ne pas l'impasse (il bloque également le fil au cours de l'opération asynchrone plutôt que de laisser le fil gratuit).
  • Je ne comprends pas bien ce que je fais ConfigureAwait(false) comme indiqué dans le lien que vous consultez. Je ne peux pas utiliser asynchrone jusqu'en tant que nécessiterait beaucoup de changements de code dans mon code.
  • Parce que vous avez ConfigureAwait(false) un seul appel à Bar ou Ros ne sera pas de blocage, mais parce que vous avez une énumération qui est la création de plus d'un et puis d'attendre sur tous ces, la première barre de blocage de la seconde. Si vous await Task.WhenAll au lieu d'attendre sur toutes les tâches, de sorte que vous ne bloquez pas l'ASP contexte, vous verrez que la méthode renvoie normalement.
  • Ah! Maintenant, je comprends. Je vous remercie.
  • Votre autre option serait d'ajouter le .ConfigureAwait(false) tout le chemin jusqu'à l'arbre jusqu'à ce que vous bloquez, de cette façon, rien n'est jamais essayer de revenir à la principale contexte; qui serait à l'œuvre. Une autre option serait de faire tourner un intérieur de contexte de synchronisation. Lien. Si vous mettez la Task.WhenAll dans un AsyncPump.Run il va bloquer efficacement sur l'ensemble de la chose sans que vous ayez à ConfigureAwait n'importe où, mais c'est probablement trop complexe en solution.
  • Double Possible de What est la différence entre la Tâche.Start/Wait et Async/Await?

InformationsquelleAutor ronag | 2012-10-30