1350 votes

Async et attendent

J'ai ouvert cette question pour une meilleure compréhension sur la façon async et await .NET 4.5 et quand les utiliser.

De ma compréhension de l'une des principales choses qui async et await faire est de rendre le code facile à lire et à écrire. Mais leur utilisation a d'autres impacts? Est-ce la même chose que la reproduction threads d'arrière-plan pour effectuer la longue durée de la logique?

J'ai lu quelques articles et je suis en train d'essayer l'exemple le plus simple. J'ai ajouté des commentaires en ligne. Pouvez vous s'il vous plaît m'aider avec quelques réponses?

// i don't uderstand why this method must be marked as "async'.
private async void button1_Click(object sender, EventArgs e)
{
    Task<int> access = DoSomethingAsync();
    // task independent stuff here

    // this line is reached after the 5 seconds sleep from 
    // DoSomethingAsync() method. Shouldn't it be reached immediately? 
    int a = 1; 

    // from my understanding the waiting should be done here.
    int x = await access; 
}

async Task<int> DoSomethingAsync()
{
    // is this executed on a background thread?
    System.Threading.Thread.Sleep(5000);
    return 1;
}

929voto

Dan Dinu Points 2618

Lors de l'utilisation d' async et await le compilateur génère un état de la machine en arrière-plan.

L'exemple que j'ai créé dans la question est vraiment salissant et n'a pas de sens (désolé). Voici un nouvel exemple qui, je l'espère, je peux expliquer en partie le haut niveau de détails qui sont en cours:

public async Task MyMethod()
{
    Task<int> longRunningTask = LongRunningOperation();
    //indeed you can do independent to the int result work here 

    //and now we call await on the task 
    int result = await longRunningTask;
    //use the result 
    Console.WriteLine(result);
}

public async Task<int> LongRunningOperation() // assume we return an int from this long running operation 
{
    await Task.Delay(1000); //1 seconds delay
    return 1;
}

Ok, donc ce qui se passe ici:

  1.  Task<int> longRunningTask = LongRunningOperation(); 
    

    commence l'exécution de LongRunningOperation

  2. le travail indépendant est effectué sur supposons le Thread Principal (Thread ID = 1) alors await longRunningOperation est atteint.

Maintenant, si le longRunningOperation n'a pas fini et est toujours en cours d'exécution, MyMethod() sera de retour à son appel de méthode, donc le thread principal n'est pas bloqué. Lorsque l' longRunningOperation est fait alors un thread du pool de threads (peut être de n'importe quel thread) sera de retour à l' MyMethod() lors de sa précédente state et de continuer l'exécution (dans ce cas l'impression que le résultat de la console).

Un deuxième cas serait que l' longRunningOperation a déjà terminé son exécution et le résultat est disponible. Quand la await longRunningOperation le runtime sait que c'est le résultat et la garder sur l'exécution de code sur le même thread. (dans ce cas le résultat de l'impression à la console).

217voto

Stephen Cleary Points 91731

De ma compréhension de l'une des principales choses qui async et await faire est de rendre le code facile à lire et à écrire.

Ils sont à faire asynchrone code facile à lire et à écrire, oui.

Est-ce la même chose que la reproduction threads d'arrière-plan pour effectuer la longue durée de la logique?

Pas du tout.

//je ne comprends pas pourquoi cette méthode doit être marquée comme "asynchrone".

L' async mot-clé permet à l' await mot-clé. De sorte que toute méthode à l'aide de await doivent être marqués async.

// cette ligne est atteint au bout de 5 secondes, le sommeil de DoSomethingAsync() la méthode. Ne devrait-elle pas être atteint immédiatement?

Non, parce qu' async méthodes ne sont pas exécuter sur un autre thread par défaut.

//est-ce exécuté sur un thread d'arrière-plan?

Pas de.


Vous pouvez trouver mon async/await intro utile. L' officiel de la MSDN docs sont aussi très bons (en particulier le ROBINET de la section), et l' async équipe a mis une excellente FAQ.

159voto

astander Points 83138

De plus pour les autres réponses, jetez un oeil à attendre (Référence C#)

et plus précisément à l'exemple inclus, il explique votre situation un peu

La suite Windows Forms exemple illustre l'utilisation de l'attendent dans un méthode async, WaitAsynchronouslyAsync. Le contraste le comportement de cette méthode avec le comportement de WaitSynchronously. Sans attendre opérateur appliqué à une tâche, WaitSynchronously s'exécute de façon synchrone en dépit de l'utilisation de l'async modificateur dans sa définition et un appel à Fil de discussion.Dormir dans son corps.

private async void button1_Click(object sender, EventArgs e)
{
    // Call the method that runs asynchronously.
    string result = await WaitAsynchronouslyAsync();

    // Call the method that runs synchronously.
    //string result = await WaitSynchronously ();

    // Display the result.
    textBox1.Text += result;
}

// The following method runs asynchronously. The UI thread is not
// blocked during the delay. You can move or resize the Form1 window 
// while Task.Delay is running.
public async Task<string> WaitAsynchronouslyAsync()
{
    await Task.Delay(10000);
    return "Finished";
}

// The following method runs synchronously, despite the use of async.
// You cannot move or resize the Form1 window while Thread.Sleep
// is running because the UI thread is blocked.
public async Task<string> WaitSynchronously()
{
    // Add a using directive for System.Threading.
    Thread.Sleep(10000);
    return "Finished";
}

53voto

Vnuk Points 1231

Je pense que vous avez choisi un mauvais exemple avec le Système.Le filetage.Fil de discussion.Sommeil.

Point de async Tâche est de le laisser exécuter en arrière-plan, sans bloquer le thread principal, telles que la réalisation d'un DownloadFileAsync.

Système.Le filetage.Fil de discussion.Le sommeil n'est pas quelque chose qui est "fait", ça dort, et donc votre prochaine ligne est atteint au bout de 5 secondes ...

La lecture de cet article, je pense que c'est une bonne explication de async et await concept: http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx

12voto

atlaste Points 4658

Pour être honnête, je pense toujours que la meilleure explication est celle à propos de l'avenir et de promesses sur Wikipedia: http://en.wikipedia.org/wiki/Futures_and_promises

L'idée de base est que vous avez un pool de threads qui exécutent des tâches de manière asynchrone. Lorsque vous l'utilisez. L'objet n'a cependant faire la promesse qu'il va lancer l'opération pendant un certain temps et vous donner le résultat lorsque vous en faites la demande. Cela signifie qu'il va bloquer lorsque vous demandez le résultat et n'a pas fini, mais s'exécute dans le thread pool autrement.

De là, vous pouvez optimiser les choses: certaines opérations peuvent être mises en œuvre async et vous pouvez optimiser des choses comme les e / s de fichier et le réseau de communication par le dosage ensemble des demandes ultérieures et/ou leur réorganisation. Je ne sais pas si c'est déjà à la tâche cadre de Microsoft, mais si ce n'est pas ce que serait l'une des premières choses que je pourrais ajouter.

Vous pouvez effectivement mettre en œuvre le futur modèle tri-de avec des rendements en C# 4.0. Si vous voulez savoir comment cela fonctionne exactement, je peux recommander ce lien qui fait un travail décent: http://code.google.com/p/fracture/source/browse/trunk/Squared/TaskLib/ . Toutefois, si vous commencez à jouer vous-même, vous remarquerez que vous avez vraiment besoin de soutien de la langue si vous voulez faire toutes les choses cool -- ce qui est exactement ce que Microsoft l'a fait.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X