posté @ Thursday, September 01, 2011 6:15 PM

Si vous êtes abonnes a ce flux, je suppose que vous connaissez déjà C# async (avec les mots-clef async et await). Ce que vous ne savez par contre peut-etre pas, c’est qu’il est tout a fait possible de creer vos propres trucs awaitable.

 

En effet, comme cela était déjà le cas avec la syntaxe Linq a l’époque de C# 3 (mots clefs where, select etc.), le mot clef “await” ne fait que déclencher un traitement de precompilation. En gros, await attend un truc, sans trop savoir ce qu’il attend. Si j’ecris la syntaxe :

 

Console.WriteLine("Calcul asynchrone d'un truc vachement complique...");
int value = await DoSomethingVeryComplicated();
Console.WriteLine(value);

 

Apres l’etape de precompilation, le compilateur voit quelque chose du genre :

 

TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
Console.WriteLine("Calcul asynchrone d'un truc vachement complique...");
var awaiter = DoSomethingVeryComplicated().GetAwaiter();
awaiter.OnCompleted(() =>
   {
      int value = awaiter.GetResult();
      Console.WriteLine(value);
      tcs.SetResult(null);
   });
return tcs.Task;

 

(je dis bien du genre, parce que je suis pas le compilateur donc je ne vois pas vraiment ce qu’il voit)

 

Un des elements qui semble completement anodin, mais qui fait la toute surpuissance du machin, c’est le “var” a la 3e ligne. En effet, un peu comme le mot clef Where cherche une methode ayant la signature Where(Func<T,bool> predicate) ce qui permet de lui faire faire un peu tout et n’importe quoi, await cherche une methode GetAwaiter() qui renvoit quelque chose ayant une methode OnCompleted(Action completion) et une methode GetResult(). Et tant que ces methodes sont presentes, ca marche !

 

Par exemple, je peux ecrire cette classe :

 

    public class MaFakeTaskJustePourEmbeterLeCompilo
    {
        private int _result;
        private bool _completed;
        private List<Action> _completions = new List<Action>();
 
        public MaFakeTaskJustePourEmbeterLeCompilo()
        {
            // truc asynchrone parce que je le veux bien
            Task.Factory.StartNew(() =>
                                      {
                                          Thread.Sleep(3000);
                                          _result = 42;
                                          NotifyCompleted();
                                      });
        }
 
 
        private void NotifyCompleted()
        {
            _completed = true;
            lock (_completions)
            {
                foreach (var c in _completions)
                    c();
                _completions.Clear();
            }
        }
 
        public void OnCompleted(Action c)
        {
            // ce code ne gere pas le SynchronisationContext courrant pour plus de lisibilite.
            // ne pas utiliser tel quel dans une appli WP7 !
            lock (_completions)
            {
                if (_completed)
                {
                    c();
                }
                else
                    _completions.Add(c);
            }
        }
        public int GetResult()
        {
            return _result;
        }
 
        public bool IsCompleted
        {
            get { return _completed; }
        }
 
        public MaFakeTaskJustePourEmbeterLeCompilo GetAwaiter()
        {
            return this;
        }
    }

 

et l’utiliser ensuite avec async :

 

Console.WriteLine("Calcul asynchrone d'un truc vachement complique...");
var value = await new MaFakeTaskJustePourEmbeterLeCompilo();
Console.WriteLine(value);

 

Maintenant, vous savez comment faire attendre un truc rigolo au mot clef await. Youhou!

 

(plus serieusement, ca peut permettre d’utiliser la syntax-sugarite de async avec des trucs pas prevus pour, et ca, c’est cool)


Commentaires :

# re: [Visual Studio Async CTP] Créez vos propres trucs awaitable
Ecrit par Mitsu le 9/1/2011 10:13 PM
Intéressant ! Je ne suis pas fan des patterns ouverts sans interface mais c'est très intéressant dans ce cas vu que le mot clé await est intégré au langage. Ca permet du coup de faire du "await compatible" un peu n'importe où sans ajouter aucune dépendance.
# re: [Visual Studio Async CTP] Créez vos propres trucs awaitable
Ecrit par Simon le 9/2/2011 12:23 PM
Ouaip !
Par contre pas sur que ca reste tel quel en RTM... vivement la build qu'on puisse toucher une version plus avancee !
# re: [Visual Studio Async CTP] Créez vos propres trucs awaitable
Ecrit par Jonathan ANTOINE le 9/2/2011 2:07 PM
Ça poutre! Merci Simon de nous faire découvrir - encore - un truc bien cool !

Ecrire un commentaire :

Titre :*
Nom *
Email
Url
Commentaire : *  


Please add 7 and 4 and type the answer here: