Getting deeper with TPL & async (Spanish version)

  • Published on
    12-Nov-2014

  • View
    53

  • Download
    0

DESCRIPTION

Presentation about the Task Parallel Library and the new async paradigm in .NET Framework.

Transcript

  • 1. Irn Reyes Fleitas

2. Temas: TPL Paralelizacin de cdigo imperativo. Programacin Paralela con tareas(Task). Colecciones de Concurrencia y Pipelines. Estructuras para la coordinacin de los datos. Async 3. Evolucin C# 4. Paralelizacin de cdigo imperativoParallel.Invoke, Parallel Loops, Cancelando, Excepciones, Particionando . Programacin Paralela con tareas(Task)Task, TimeOuts, Cancelando, Excepciones, Retornando valores. Colecciones de Concurrencia y PipelinesConcurrentQueue, ConcurrentStack, ConcurrentBag, BlockingCollection,ConcurrentDictionary. 5. Parallel Class( System.Threading.Tasks )Parallel.ForParallel.ForEachParallel.Invoke 6. Parallel.InvokeLa manera ms simple de paralelizar varios mtodos.Sintaxis:Invoke( Action [] )Invoke( ParallelOptions, Action [] )No se tiene garanta de orden.No retorna hasta que cadainvocacin no hay finalizado.GoToRiver GoToPark GoToZoo GoToPlainAreaParallel.Invoke(Walk.GoToPark, Walk.GoToRiver, Walk.GoToZoo, Walk.GoToPlainArea);Parallel.Invoke(() => Walk.GoToPark("Santiago"),Walk.GoToRiver,delegate() { Walk.GoToZoo("26st"); },Walk.GoToPlainArea);PatrnFork/Join 7. 3 posibles escenarios de paralelismo EscenarioIdealEjemplo hipottico con una arquitectura con4 ncleos lgicos.1era ejecucinGoToZooGoToRiverGoToParkGoToPlainArea2da ejecucinGoToParkGoToRiverGoToPlainAreaGoToZoo3era ejecucinGoToZooGoToPlainAreaGoToRiverGoToPark 8. Ventajas y Desventajas1. Es un mtodo muy simple de lograr paralelismo sin tareas, ni hilos.1. Mtodos con notables diferencias en cuanto al tiempo de ejecucin.2. Cada llamada crea una sobrecarga antes de correr los mtodos.3. Como todo cdigo en paralelo, esta expuesto a existencias deinterdependencia e incontrolables interacciones.4. No tiene garanta de orden. 9. Anlisis de tiempo con respecto al secuencialWalk.GoToPark();Walk.GoToRiver();Walk.GoToZoo();Walk.GoToPlainArea();Ejemplo hipottico (figuras)con unaarquitectura con 4 ncleos lgicos ymediciones con 2 ncleos lgicosParallel.Invoke(Walk.GoToPark, Walk.GoToRiver, Walk.GoToZoo, Walk.GoToPlainArea); 10. Parallel.ForVersin paralelizada del clsico for.Sintaxis:For( Int32, Int32, Action )For( Int32, Int32, Action )List data = new List(){"Estamos","paralelizando","el","for","y","el","foreach"};Tradicional Paralelizadofor (int i = 0; i < data.Count; i++){Console.Write(i);}Parallel.For(0, data.Count, x =>{Console.Write(x);});No tiene por que cumplirse el orden.Tener en cuenta si los elementosestan relacionados entre si.Desde LowerBound a UpperBound.El primer parmetro es inclusivo,el segundo exclusivo.Load-BalancePequeos bodies. 11. Anlisis de tiempo con respecto al secuencial(RayTracing)void Render(Scene scene, Color[,] rgb){for (int y = 0; y < screenHeight; y++){for (int x = 0; x < screenWidth; x++)rgb[x,y] = TraceRay(new Ray(scene,x,y));}}void Render(Scene scene, Color[,] rgb){Parallel.For(0, screenHeight, delegate(int y){for (int x = 0; x < screenWidth; x++)rgb[x,y] = TraceRay(new Ray(scene,x,y));});}Ocho ncleos y 350 x 350Secuencial: 1.7 fpsParalelo : 12 fpsDos ncleos y 350 x 350Secuencial: 1.0 fpsParalelo : 2.0 fpsDos ncleos y 578 x 485Secuencial: 0.5 fpsParalelo : 1.0 fps 12. Anlisis de tiempo con respecto al secuencial(Primos)List primes = new List();int cotaSup = 50000;for (int i = 2; i < cotaSup; i++){if (isPrime(i))primes.Add(i);}Parallel.For(2, cotaSup, (i) =>{if (isPrime(i))primes.Add(i);});0.5 segundos0.2 segundos0.5/0.2 = 2.5xEjemplo hipottico (figuras)con unaarquitectura con 4 ncleos lgicos ymediciones con 2 ncleos lgicos 13. F#let sentences = [|"Estamos"; "paralelizando"; "el"; "for"; "y"; "el";"foreach"|]for index=0 to sentences.Length doprintfn "%d" indexprintfn ""let accion indice =printfn "%d" indiceParallel.For(0,sentences.Length, new Action(accion))Console.ReadKey(); 14. Parallel.ForEachVersin paralelizada del clsico foreach.Sintaxis:ForEach ( IEnumerable , Action )ForEach ( IEnumerable , Action )List data = new List(){"Estamos","paralelizando","el","for","y","el","foreach"};foreach (var items in data){Console.Write(items + " ");}Tradicional ParalelizadoParallel.ForEach(data, x =>{Console.Write(x + " ");}); 15. Anlisis de tiempo con respecto al secuencialEjemplo hipottico (figuras)con unaarquitectura con 4 ncleos lgicos ymediciones con 2 ncleos lgicosforeach (var i in inputData){if (isPrime(i))resultData[indice] = i;indice++;}28 segundos14 segundosvar op = Partitioner.Create(inputData);Parallel.ForEach(op, (item, loopState, index) =>{28/14 = 2xif (isPrime(item))resultData[index] = item;}); 16. Como paramos los ciclos?(Cancelando)ParallelLoopState ParallelLoopResultParallelLoopResult loopResult1 = Parallel.For(0, 10, (x, state) =>{if (x < 5)Console.WriteLine(x);elsestate.Stop();});ParallelLoopResult loopResult2 = Parallel.ForEach(data, (x, state) =>{if (!x.Equals("y"))Console.WriteLine(x);elsestate.Break();});Console.WriteLine(loopResult1.LowestBreakIteration);Console.WriteLine(loopResult1.IsCompleted);Console.WriteLine(loopResult2.LowestBreakIteration);Console.WriteLine(loopResult2.IsCompleted); 17. Manejo de ExcepcionesAggregateExceptionFormato:try{..........}catch (AggregateException aggEx){foreach (Exception ex in aggEx.InnerExceptions){Console.WriteLine(string.Format("Caught exception '{0}'",ex.Message));}} 18. Manejo de ExcepcionesEjemplo:try{ParallelLoopResult loopResult = Parallel.For(0, 10, (x, state) =>{if (x < 5)Console.WriteLine(x);else{var ex = "Excepcin en el ndice " + x;throw new InvalidDataException(ex);}});Console.WriteLine("Ciclo for completado: {0}", loopResult.IsCompleted);}catch (AggregateException aggEx){foreach (var innerException in aggEx.InnerExceptions){//Pueden haber 2 excepciones a causa del paralelismo.Console.WriteLine("Excepcion capturada: " + innerException.Message);}} 19. ParallelOptionsParallelOptions.MaxDegreeOfParallelismParallelOptions.TaskSchedulerParallelOptions.CancellationTokenSe utilizan en losmtodos de Parallel.var source = Enumerable.Range(8, 2000).ToArray();double[] result = new double[source.Length];ParallelOptions parallelOptions = new ParallelOptions();parallelOptions.MaxDegreeOfParallelism = Environment.ProcessorCount*2; //EjemploParallel.ForEach(Partitioner.Create(8, source.Length),parallelOptions, range =>{for (int i = range.Item1; i < range.Item2; i++)result[i] = source[i]*Math.E;}); 20. ParticionandoParticin por rangos Particin por bloquesPartitioner.Create(1,40)Parallel.ForEach(Partitioner.Create(10, 200), range =>{Console.WriteLine("{0},{1}",range.Item1,range.Item2);for (int i = range.Item1; i < range.Item2; i++){data[i] = data[i]*i;}});Optimizando el particionado segn el nmero de ncleos.Partitioner.Create(1,40, ((numeroDeElementos/numeroDeNucleos)+1))System.Environment.ProcessorCountSintaxis:Create ( IEnumerable )Create ( Int32, Int32)Create ( Int32, Int32, Int32) 21. Paralelizacin de cdigo imperativoParallel.Invoke, Parallel Loops, Cancelando, Excepciones, Particionando . Programacin Paralela con tareas(Task)Task, TimeOuts, Cancelando, Excepciones, Retornando valores. Parallel Linq (PLinq)Operadores, Cancelando, Agregaciones, Excepciones. Colecciones de Concurrencia y PipelinesConcurrentQueue, ConcurrentStack, ConcurrentBag, BlockingCollection,ConcurrentDictionary. 22. Task 23. Task - Scheduling 24. Ciclo de vida y estado de una tareaEnumTaskStatusMiembros:CreatedWaitingForActivationWaitingToRunRunningWaitingForChildrenToCompleteRanToCompletionCanceledFaulted 25. Invocando TareasGenerateSomething GenerateNothingParallel.Invoke(GenerateSomething,() => GenerateNothing());//Los mtodos no estn corriendo todava, pero las tareasestn listas para empezar.//El estado para ambas tareas es TaskStatus.Created.var task1 = new Task(GenerateSomething);var task2 = new Task(() => GenerateNothing());task1.Start();task2.Start();Task.WaitAll(task1, task2);var task1 = Task.Factory.StartNew(() => GenerateNothing()); 26. TimeOutsvar task1 = new Task(GenerateSomethingTimeOut);var task2 = new Task(() => GenerateNothing());task1.Start();task2.Start();if(!Task.WaitAll(new Task[]{task1,task2},300)){Console.WriteLine("GenerateSomething y GenerateNothing han tardado ms de300ms");}if(!task1.Wait(300)){Console.WriteLine("GenerateSomething ha tardado ms de 300ms");} 27. Manejando excepciones con las Taskstatic void GenerateSomethingCancel(CancellationToken cancellationToken){cancellationToken.ThrowIfCancellationRequested();Console.WriteLine("GenerateSomething");Thread.Sleep(3000);if (sw.Elapsed.Seconds > 1)throw new TimeoutException("La tarea se demor mas de 1 segundos");cancellationToken.ThrowIfCancellationRequested();}try{// Espera por que todas las tareas finalicen en menos de 3 segundosif (!Task.WaitAll(new Task[] { task1, task2 }, 3000)){Console.WriteLine("GenerateSomething y GenerateNothing han tardado ms de 300ms en terminar");Console.WriteLine(task1.Status.ToString());Console.WriteLine(task2.Status.ToString());}}catch (AggregateException ex){foreach (Exception innerEx in ex.InnerExceptions){Console.WriteLine(innerEx.ToString());}} 28. Retornando valores desde las tareasstatic List GenerateSomethingReturn(){Console.WriteLine("GenerateSomething");Thread.Sleep(3000);return new List{"Estoy","retornando","una","lista","de","strings."};}var task1 = Task.Factory.StartNew(() => GenerateSomethingReturn());try{task1.Wait();}catch (AggregateException ex){foreach (Exception innerEx in ex.InnerExceptions){Console.WriteLine(innerEx.ToString());}}var task2 = Task.Factory.StartNew(() =>{foreach (var result in task1.Result){Console.WriteLine(result);}}); 29. Cancelando Tareas usando TokensCancellationToken cancellationTokenCancellationTokenSourceSe pasa como parmetroControla la cancelacin desde el mtodo principalstatic void GenerateSomethingCancel(CancellationToken cancellationToken){cancellationToken.ThrowIfCancellationRequested();Console.WriteLine("GenerateSomething");Thread.Sleep(3000);cancellationToken.ThrowIfCancellationRequested();}var cts = new CancellationTokenSource();var ct = cts.Token;var task1 = Task.Factory.StartNew(() => GenerateNothingCancel(ct),ct);cts.Cancel();if (task1.IsCanceled){Console.WriteLine("La Tarea GenerateSomethingCancel que estaba en ejecucion fue cancelada");} 30. TaskCreationOptionsOptimizando el cdigoTaskCreationOptions.AttachedToParentTaskCreationOptions.NoneTaskCreationOptions.LongRunningTaskCreationOptions.PreferFairnessvar task2 = Task.Factory.StartNew(() =>Ayudar al Scheduler{foreach (var result in task1.Result){Console.WriteLine(result);}},TaskCreationOptions.PreferFairness); 31. Concatenando mltiples tareas usando Continuacintry{var task1 = Task.Factory.StartNew(() => GenerateSomethingCancelReturn(ct), ct);var task2 = task1.ContinueWith(t =>{foreach (var result in t.Result){Console.WriteLine(result);}});task1.Wait();}catch (AggregateException ex){foreach (Exception innerEx in ex.InnerExceptions){Console.WriteLine(innerEx.ToString());}}var task2 = Task.Factory.StartNew(() =>{foreach (var result in task1.Result){Console.WriteLine(result);}}); 32. var f = Task.Factory;var build1 = f.StartNew(() => Build(project1));var build2 = f.StartNew(() => Build(project2));var build3 = f.StartNew(() => Build(project3));var build4 = build1.ContinueWith(() => Build(project4));var build5 = f.ContinueWhenAll(new[] { build1, build2, build3 }, () => Build(project5));var build6 = f.ContinueWhenAll(new[] { build3, build4 }, () => Build(project6));var build7 = f.ContinueWhenAll(new[] { build5, build6 }, () => Build(project7));var build8 = build5.ContinueWith(() => Build(project8));Task.WaitAll(build1, build2, build3, build4, build5, build6, build7, build8); 33. Mezclando paralelismo y cdigo secuencial con Continuacin 34. TaskContinuationOptionsTaskContinuationOptions.AttachedToParentTaskContinuationOptions.ExecuteSynchronouslyTaskContinuationOptions.LongRunningTaskContinuationOptions.PreferFairnessTaskContinuationOptions.NoneTaskContinuationOptions.NotOnCanceledTaskContinuationOptions.NotOnFaultedTaskContinuationOptions.NotOnRanToCompletionTaskContinuationOptions.OnlyOnCanceledTaskContinuationOptions.OnlyOnFaultedTaskContinuationOptions.OnlyOnRanToCompletionvar task2 = task1.ContinueWith(t =>{foreach (var result in t.Result){Console.WriteLine(result);}},TaskContinuationOptions.None);Especificando el comportamientode la prxima tareaCondicionando la prxima tarea 35. Anlisis de tiempo con respecto a los ThreadEjemplo hipottico con una arquitecturacon 2 ncleos lgicos.64 Threads versus 64 Tasks1. Los primos hasta el 50 : Thread 0.9 segundos.Tasks 0.2 segundos.2. Los primos hasta el 500 : Thread 2 segundos.Tasks 1 segundo.3. Los primos hasta el 5000 : Thread 15 segundos.Tasks 13 segundos.4. Los primos hasta el 50000: Thread 116 segundos.Tasks 104 segundos. 36. Paralelizacin de cdigo imperativoParallel.Invoke, Parallel Loops, Cancelando, Excepciones, Particionando . Programacin Paralela con tareas(Task)Task, TimeOuts, Cancelando, Excepciones, Retornando valores. Colecciones de Concurrencia y PipelinesConcurrentQueue, ConcurrentStack, ConcurrentBag, BlockingCollection,ConcurrentDictionary. 37. var data = new List();Parallel.ForEach(Partitioner.Create(0, 200), range =>{for (int i = range.Item1; i < range.Item2; i++)lock (data)data.Add(i);});data.ForEach(x => Console.Write(x + " "));Solucin 38. Colecciones Thread-Unsafe:System.CollectionsSystem.Collections.GenericColecciones Thread-Safe:System.collections.ConcurrentConcurrentQueueConcurrentStackConcurrentBagConcurrentDictionaryBlockingCollectionIProducerConsumerCollection 39. Colecciones de concurrencia ideales paraescenarios productor-consumidor. 40. ConcurrentQueueLock-FreeMtodos Importantes:EnqueueTryDequeueTryPeek 41. ConcurrentQueue-Esta coleccion es completamente libre de lock (lock-free)-Usa compare and swap (CAS)-Cuando falla una operacion CAS se pone en estado decontencion. 42. ConcurrentQueue-Produce (over-head).-Mejora el rendimiento de la cola y otras coleccionesthread-unsafe, en determinados escenarios.-Nos facilita el trabajo con la concurrencia. 43. ConcurrentQueueCaracteristicas importantes:concurrentQueue.Enqueue(item);if (concurrentQueue.TryPeek(out item)){DoSomething(item);}if (concurrentQueue.TryDequeue(out item)){DoSomething(item);} 44. ConcurrentStackMtodos Importantes:PushTryPopTryPeek 45. ConcurrentStackOtros Mtodos:PushRangePopRange 46. ConcurrentStack-Similar a la coleccion ConcurrentQueue.-Es una coleccion LIFO.-Atomicidad en los metodos PushRange y PopRange reduce la cantidadde insersiones y extracciones concurrentes en la coleccion. 47. ConcurrentStackCaracteristicas importantes:concurrentStack.Push(item);if (concurrentStack.TryPeek(out item)){DoSomething(item);}if (concurrentStack.TryPop(out item)){DoSomething(item);} 48. ConcurrentStackCaracteristicas importantes:Parallel.ForEach(Partitioner.Create(0, partCount), p =>{concurrentStack.PushRange(numberArray, p.Item1, p.Item2 - p.Item1);}); 49. ConcurrentStackSintaxis:count = s.TryPopRange(numberArray, 0, numberArray.Length);count = s.TryPopRange(numberArray);Count sera la cantidad de objetos que fueron sacados del tope dela cola e insertados el el array. 50. TPL - Colecciones de Concurrencia y PipelinesAtomiciadad o costoPushRangeTryPopRangePushTryPopBuen rendimientoIgual concurrenciaNo Over-HeadNo memoriaadicionalOver-HeadMemoria adicionalAtomiciadadMenorconcurrencia 51. ConcurrentBagMtodos Importantes:AddTryTakeTryPeekNota:Coleccin donde el orden no importa.Ideal para escenarios Productor Consumidor. 52. ConcurrentBag-Ideal para ciertos escenarios productor-consumidor.-No es completamente lock-free.-Bastante ineficiente, donde el hilo productor es distinto al consumidor.-Mantiene una cola local para cada hilo que accede a ella. 53. ConcurrentBagCaracteristicas importantes:sentencesBag.Add(s.ToString());string sentence;if (_sentencesBag.TryTake(out sentence)){_capWordsInSentencesBag.Add(CapitalizeWords(delimiterChars, sentence, ''));} 54. BlockingCollectionMtodos Importantes:AddTryAddTakeTryTakeCompleteAddingGetConsumerEnumerableOfrece soporte para Bounding y Blocking.Ideal para escenarios Productor Consumidor.Ideal para implementaciones de pipelines.Capacidad mxima opcional.Permite cancelacin a travs de tokens.Es un wrapper para una interfaz del tipo IProducerConsumerCollectionExisten 2 tipos de enumeraciones con foreach:1. Enumeracin de solo lectura.2. Enumeracin que elimina los elementos que han sido enumerados(P-C). 55. BlockingCollectionCaracteristicas importantes:BlockingCollection stackBC = new BlockingCollection(new ConcurrentStack());BlockingCollection bagBC = new BlockingCollection(new ConcurrentBag());BlockingCollection bc = new BlockingCollection(count); 56. BlockingCollectionCaracteristicas importantes:IsCompleted, IsAddingCompleted.string aux;while (!sentences.IsCompleted){if (sentences.TryTake(out aux))upperSentences.Add(aux.ToUpper());}upperSentences.CompleteAdding(); 57. BlockingCollectionCaracteristicas importantes:GetConsumingEnumerable()foreach (var item in upperSentences.GetConsumingEnumerable()){finalSentences.Add(item.Replace("U", ""));}upperSentences.CompleteAdding(); 58. BlockingCollectionCaracteristicas importantes:if (!_sentencesBC.TryAdd(newSentence, 2000, cancToken)){throw new TimeoutException("_sentencesBC took more than 2 seconds to add an item");}catch (OperationCanceledException ex){// The operation was cancelledbreak;} 59. BlockingCollectionCaracteristicas importantes:BlockingCollection.AddToAny(Output, result, _token);BlockingCollection.TryAddToAny(Output, result,timeOut, _token); 60. BlockingCollectionCaracteristicas importantes:BlockingCollection.AddToAny(array, item, _token);BlockingCollection.TryAddToAny(array, item,timeOut, _token);Estos metodos devuelven el indice de la coleccion, en el array decolecciones, a la cual se le agrego el elemento. 61. BlockingCollectionCaracteristicas importantes:BlockingCollection.TakeFromAny(array, out item, _token);BlockingCollection.TakeFromAny(array, out item,timeOut, _token);Estos metodos devuelven el indice de la coleccion, en el array decolecciones, de la cual se elimino el elemento. 62. BlockingCollection-Facilita el trabajo con las colecciones thread-safe.-Produce Over-Head.-Disminuye la cantidad y simplfica la complejidad del codigo.-Ideal para la implementacion de pipelines(Ejemplo) 63. ConcurrentDictionaryLock-Free paraoperaciones delecturaMtodos Importantes:AddOrUpdateGetEnumeratorGetOrAddTryAddTryGetValueTryRemoveTryUpdateSintaxis:ConcurrentDictionary()ConcurrentDictionary(Int32, Int32)int initialCapacity = 100;int concurrencyLevel = Environment.ProcessorCount * 2;ConcurrentDictionary cd = new ConcurrentDictionary(concurrencyLevel, initialCapacity);for (int i = 0; i < 64; i++)cd[i] = i * i;Console.WriteLine(23 is {0} (should be {1})", cd[23], 23 * 23); 64. ConcurrentDictionaryCaracteristicas importantes:_rectanglesDict.AddOrUpdate(newKey, newRect,(key, existingRect) =>{if (existingRect != newRect){lock (existingRect){existingRect.Update(newRect.Location, newRect.Size);}return existingRect;}else {return existingRect;}}); 65. AsynchronousProgrammingModel(APM)Event-basedAsynchronousPattern(EAP)TaskAsynchronousPattern(TAP)Patrones estndaresIdeaSincrnico = AsincrnicoTAPAPMEAP 66. Microsoft Visual Studio AsyncCommunity Technology Preview (CTP).( Visual Studio Async CTP )Nuevas keywords:async:await:Marca a mtodos o expresiones lambdas como asincrnicas.Retiene el control hasta que la operacin asincrnica termine.Objetivo:Programacin asincrnica = Programacin sincrnica.Escribir cdigos simples y fciles de entender.Fin de los mtodos callback. 67. public int SumPageSizes(IList uris){int total = 0;foreach (var uri in uris){statusText.Text = string.Format("Found {0} bytes ...", total);var data = new WebClient().DownloadData(uri);total += data.Length;}statusText.Text = string.Format("Found {0} bytes total", total);return total;}Versin SincrnicaProblemas:Bloquea la interfaz de usuario.No nos va enseando el estado de la descarga.Solucin Versin Asincrnica 68. Versin Asncrona con EAPpublic void SumPageSizesAsync(IList uris){SumPageSizesAsyncHelper(uris.GetEnumerator(), 0);}private void SumPageSizesAsyncHelper(IEnumerator enumerator, int total){if (enumerator.MoveNext()){statusText.Text = string.Format("Found {0} bytes ...", total);var client = new WebClient();client.DownloadDataCompleted += (sender, e) => SumPageSizesAsyncHelper(enumerator,total + e.Result.Length);client.DownloadDataAsync(enumerator.Current);}else{statusText.Text = string.Format("Found {0} bytes total", total);enumerator.Dispose();}}Problemas:Hay que romper el foreach.En cada llamado se ancla un evento.El cdigo es recursivo.No retorna el total una ves calculado. 69. ConclusionesEl mtodo anterior es asincrnico con una sola llamada asincrnica y una solaestructura de control alrededor de esta. Imagnense ms llamadas asincrnicasy ms estructuras de control, sera un verdadero caos.Primera solucin: Utilizar APM o EAP con las nuevas clases de TPL.Segunda solucin: Utilizar TAP(junto a async).public async Task SumPageSizesAsyncBest(IList uris){int total = 0;foreach (var uri in uris){statusText.Text = string.Format("Found {0} bytes ...", total);var data = await new WebClient().DownloadDataTaskAsync(uri);total += data.Length;}statusText.Text = string.Format("Found {0} bytes total", total);listBox1.Items.Add(total.ToString());return total;} 70. let asyncProcessFile (filePath : string) =async {printfn "Procesando fichero [%s]" (Path.GetFileName(filePath))use fileStream = new FileStream(filePath,FileMode.Open)let bytesToRead = int fileStream.Lengthlet! data = fileStream.AsyncRead(bytesToRead) //Returna un objeto Asyncprintfn Se leyeron [%d] bytes" data.Lengthuse resultFile = new FileStream(filePath + ".results", FileMode.Create)do! resultFile.AsyncWrite(data,0,data.Length)printfn "Finalizado el procesamiento del archivo [%s]" Async.StartasyncProcessFile "./testAsync.txt"Console.ReadKey();async en F# 71. Retornopublic async void SumPageSizesAsyncBestOther(IList uris){int total = 0;foreach (var uri in uris){statusText.Text = string.Format("Found {0} bytes ...", total);var data = await new WebClient().DownloadDataTaskAsync(uri);total += data.Length;}statusText.Text = string.Format("Found {0} bytes total", total);listBox1.Items.Add(total.ToString());}( Fire and forget )private async void sumButton_Click(object sender, RoutedEventArgs e) {sumButton.IsEnabled = false;await SumPageSizesAsync(GetUrls()));sumButton.IsEnabled = true;}( Incluyendo genricas) 72. Cdigo final propuestopublic async Task SumPageSizesAsyncBetter(IList uris){var tasks = from uri in uris select new WebClient().DownloadDataTaskAsync(uri);var data = await TaskEx.WhenAll(tasks);return await TaskEx.Run(() =>data.Sum(s => s.Length));}Nota:Se propone incluir Run() y WhenAll() en la claseTask cuando async arrive a suversin final; mientras este en CTP se alojarn en una clase de prueba llamadaTaskEx. 73. Como funciona async?Original Transformado por el compiladorpublic static async Task DoSum(int from,int to){int result = await Sum(from, to);string param = result.ToString() + "rn";File.AppendAllText(@"./result.txt", param);}public static Task Sum(int from, int to){Task sum = TaskEx.Run(() =>{int result = 0;for (int i = from; i Sum(from,to));return task1.ContinueWith((antecedentTask) =>{string param = antecedentTask.Result.Result.ToString() + rn";File.AppendAllText(@"./result.txt", param);});}public static Task Sum(int from, int to){Task sum = TaskEx.Run(() =>{int result = 0;for (int i = from; i Async.StartThread.Sleep(2000)Async.CancelDefaultToken() 77. Excepciones desde asynctry{string txt = await w.DownloadStringTaskAsync(url);}catch(WebException x){--- Handle exception.}let asyncOperation =async {try// ...with| :? IOException as ioe ->printfn "IOException: %s" ioe.Message| :? ArgumentException as ae ->printfn "ArgumentException: %s" ae.Message}Las excepcionesse manejanigual que demanerasincrnica.