Wygday 2011 - C#5 Async CTP - Reactive Extensions

Post on 22-Jun-2015

2.993 views 2 download

Tags:

description

Wygday - C#5 Async CTP - Reactive Extensions

Transcript of Wygday 2011 - C#5 Async CTP - Reactive Extensions

C# 5/Rx Extensions :Vers un développement asynchrone

Giovanni Clement WygwamEric Vernié Microsoft

Motivations

Point de rupture

La programmation parallèle est un art difficile

Example de code séquentiel (C#)

for (int z = 0; z < nbandesReel; z++) { int offSetpositiony = (tailleBandeY) * (z); a = xmin; b = (ymin) + (intigralY * tailleBandeY) * z; Bitmap bmp = DessinerBandeUnsafe(b,width ,tailleBandeY); Rectangle rect = new Rectangle(0, offSetpositiony, width, tailleBandeY); Gfx.DrawImage(bmp, rect);} //Code omis pour plus de clarté

Code parallèle manuelManualResetEvent mre = new ManualResetEvent(false); ReaderWriterLockSlim lck = new ReaderWriterLockSlim(); int z = 0; int restant = nbandesReel; for (z = 0; z < nbandesReel; z++) { param.b = (ymin) + (intigralY * tailleBandeY) * z; param.offSetpositiony = (tailleBandeY) * (z); ThreadPool.QueueUserWorkItem((object userState) => { Parametres p = (Parametres)userState; Bitmap bmp = this.DessinerBandeUnsafe(p.b, p.width, p.tailleBandeY); Rectangle rect = new Rectangle(0, p.offSetpositiony, p.width, p.tailleBandeY); try { lck.EnterWriteLock(); Gfx.DrawImage(bmp, rect); } finally { lck.ExitWriteLock(); } if (Interlocked.Decrement(ref restant) == 0) mre.Set(); }, param); } mre.WaitOne(); SynchroSurMandelbrotComplete(); }

Il est donc urgent de simplifier !!

Microsoft nous aide avec la Task Parallel Library

Task Parallel Library (.NET)

Parallel.For(0, nbandesReel, 1, (z) => { int offSetpositiony = (tailleBandeY) * (z); b = (ymin) + (intigralY * tailleBandeY) * z; Bitmap bmp = this.DessinerBandeUnsafe(b, width, tailleBandeY); Rectangle rect = new Rectangle(0, offSetpositiony, width, tailleBandeY); this.SyncroDessinerFractal(new DessinerEventArgs(bmp, rect, true));

});

Chaque itération est une tâche

Toutes les tâches doivent êtres finies avant de poursuivre

DEMOLes Tasks en action

Penser Parallèle

Décomposition du code

Modèle de Programmation Parallèle Visual Studio 2010

.NET C++

DonnéesTask Parallel Library

Parallel LINQParallel Patterns Library

Tâches Task Parallel Library Parallel Patterns Library

Flux Données Asynchronous Agents Library

L’offre parallèle de Visual Studio 2010

aujourd’hui

Nouvelle librairie TPL DataFlow

Pipeline

Coordination orientée événements

Modélisation orientée flux de données

Jeux de primitives (blocs) pour communiquer par message au sein d’un processus

1. Penser “Mise en tampon + traitement” 2. Construit au dessus des Tâches TPL, des collections concurrentes,

…3. Les “Blocs Dataflow” peuvent êtres mis en liaisons pour créer des

réseaux de communication

Repose sur des concepts / designs provenant1. Dix ans d’expérience en recherche en informatique2. Inspiré d’implémentations Microsoft

Asynchronous Agents library dans Visual C++ 2010 CCR de Microsoft Robotics

Introduction à TPL DataFlow

Nouvelle librairie orientée flux de données

Blocs de flux de données

Tampon Exécution

Jointure

Bloc pour stocker des donnéesBufferBlock<T>

private var _buffer = new BufferBlock<int>(); private static void Producer(){ while(true) { int item = Produce();

_buffer.Post(item); }}

private static async void ConsumerAsync(){ while(true) { int item = await _buffer.ReceiveAsync(); Process(item); }}

Bloc d’exécutionActionBlock<TInput>

var actionWrite = new ActionBlock<int>(item => Console.WriteLine(item));

var buffer = new BufferBlock<int>();

buffer.LinkTo(actionWrite);

for (int i = 0; i < 10; i++) buffer.Post(i);

Bloc d’ExécutionTransformBlock<TInput,TOutpu

t>

var transformPow = new TransformBlock<double, double>(d => Math.Pow(d, 2));var transformSqrt = new TransformBlock<double, double>(d => Math.Sqrt(d));var actionWrite = new ActionBlock<double>(d => Console.WriteLine(d));

transformPow.LinkTo(transformSqrt);transformSqrt.LinkTo(actionWrite);

for (double d = 0; d < 10; d++) transformPow.Post(d);

Bloc pour stocker des données BroadcastBlock<T>

var broadcast = new BroadcastBlock<int>(_ => _);

var buffer1 = new BufferBlock<int>();var buffer2 = new BufferBlock<int>();

broadcast.LinkTo(buffer2);broadcast.LinkTo(buffer1);

for (int i = 0; i < 10; i++){ broadcast.Post(i);}

for (int i = 0; i < 10; i++){ Console.WriteLine("Buffer1 " + buffer1.Receive()); Console.WriteLine("Buffer2 " + buffer2.Receive());}

DEMOTPL DataFlow en action

Penser parallèle et structurer l’application doit donc devenir une seconde

nature afin que l’application monte

efficacement en charge.

Mais développer parallèle, ce n’est pas que la

performance !!

C’est aussi l’asynchronisme

Asynchronous Programming Model (APM)1. IAsyncResult BeginRead(byte[] array,int offset,int

numBytes, AsyncCallback userCallback,object stateObject)

2. int EndRead(IAsyncResult asynResult)

Event-based Asynchronous Pattern (EAP)1. void SendAsync( IPAddress address, Object

userToken )2. pingSender.PingCompleted += new

PingCompletedEventHandler (PingCompletedCallback);

Modèles existant

Task-based Asynchronous Pattern (TAP)1.Task, et Task<Tresult>2.Nouvelles fonctionnalités du

langage C# 5 async et await

Reactive Extensions

Nouveaux Modèles

TAP : Comment ça marche ?

async Task<XElement> GetRssAsync(string url) { var client = new WebClient(); var task = client.DownloadStringTaskAsync(url); var text = await task; var xml = XElement.Parse(text); return xml;}

async Task<XElement> GetRssAsync(string url) { var client = new WebClient(); var task = client.DownloadStringTaskAsync(url); var text = await task; var xml = XElement.Parse(text); return xml;}

TAP Comment ça marche ?Task<XElement> GetRssAsync(string url) {

var $builder = AsyncMethodBuilder<XElement>.Create(); var $state = 0; TaskAwaiter<string> $a1; Action $resume = delegate { try { if ($state == 1) goto L1; var client = new WebClient(); var task = client.DownloadStringTaskAsync(url); $state = 1; $a1 = task.GetAwaiter(); if ($a1.BeginAwait($resume)) return; L1: var text = $a1.EndAwait(); var xml = XElement.Parse(text); $builder.SetResult(xml); } catch (Exception $ex) { $builder.SetException($ex); } }; $resume(); return $builder.Task;}

DEMOTAP en action

• Bonne intégration avec Tasks• await sur méthodes de TaskEx (Run ou AwaitAll)• Transformation Task<T> en T au retour de await

• Support de l’annulation• CancellationTokenSource

• Gestion des exceptions• try/catch autour de await• OperationCanceledException pour annulation

C# Async composition

Reactive Extension

« Asynchronisme »Une tache est asynchrone, SSI son éxécution ne bloque pas le contexte applicatif dans lequel elle se trouve.

Reactive Extension

• Besoin d’une interface graphique fluide

• Consommation de services

• Applications connectées …

Reactive Extension

Rx Extensions <-> Reactive Extensions

Ensemble d’outils (extensions) facilitant la gestions de taches / contextes asynchrones dans vos applications.

Reactive Extension

FluentMethode chaining :

Nouveau context Dernier contextFacilité de débugging

Ubiquitaire

Producer / Consumers d’events Finit les multitudes de callbacks a gérer

Reactive Extension

Comment c’est fait ?

1 DLL principale : System.Reactive

Reactive Extension

Comment c’est fait ?

Utilise : Threading de la BCL (TPL) Collections Threadsafe Runtime objects

Reactive Extension

2 Interfaces à retenir :1. IObserver<T>2. IObservable<T>

Reactive Extension

Observable/Observer <T>• Souscription

• Enumerator action : OnNext Delegate se déroulant à chaque item.

• OnError Delegate se déroulant lors d’une erreur

• OnCompletedDelegate se déroulant lorsque la tache est terminée

Reactive Extension

Observable/Observer <T>• Souscription

• La séquence est envoyée vers les souscriptions

• A chaque donnée de séquence, le delegate reçoit l’item typé => C’est à vous d’y placer une logique.

• A chaque mise à jour de la source de données, les nouvelles séquences sont également envoyées.

Reactive Extension

Observable/Observer <T>• Linq to Observable

DEMORx Extensions : Premier pas

Reactive Extension

« Based events programming »• Utilisation des events comme

séquence de données requêtables.

• Ainsi, par exemple un evènement MouseMove (Forms) se transforme en une séquence de données, requétables.

Reactive Extension

« Based events programming »• L’ObservableCollection contient une

séquence de données, « live », correspondant au retour de l’évènement lié.

• Il devient donc facile de consommer de façon asynchrone cette séquence de données, vers plusieurs « points » / souscriptions

DEMORx Extensions : Drag & drop

Reactive Extension

« Producers / Consumers »

• Une source IEnumerable<T> peut devenir Observable<T>.

• Une source Observable<T> peut être « publiée » vers des consommateurs.

• Une source Observable<T> peut être consommée de X manières, ou X est le nombre de souscriptions.

Reactive Extension

« Producers / Consumers »

• On peut imaginer un flux de données extrait d’un WebService :• 3 souscriptions dans l’application :

• L’onglet News de l’application• L’onglet Tag • L’onglet Catégories

• Chaque onglet est alors mis à jour en live.

Reactive Extension

Conclusion

• Reactive extensions = Reactive programming

• Facilite et simplifie l’écriture d’applications asynchrones ( WinForms, WPF, WPhone7…)

• Réponses à de nombreuses problématiques de développement asynchrones

Visual Studio Async CTP (SP1 Refresh)1. http://www.microsoft.com/downloads/en/details.aspx?Fam

ilyID=4738205d-5682-47bf-b62e-641f6441735b&displaylang=en

TPL Dataflow1. http://msdn.microsoft.com/en-us/devlabs/gg585582

Asynchronous Programing Model 1. http://msdn.microsoft.com/fr-fr/library/ms228969(v=VS.85

)

Event-Based Asynchronous Pattern 1. http://msdn.microsoft.com/fr-fr/library/hkasytyf(v=VS.85).

aspx

http://blogs.msdn.com/b/devpara/

Ressources

RxExtensionshttp://msdn.microsoft.com/en-us/data/gg577609

Introductionhttp://msdn.microsoft.com/en-us/data/gg577611

Sampleshttp://rxwiki.wikidot.com/101samples

Ressources