miércoles, 16 de diciembre de 2015

C# Accessor Delegates Exception

Si usted usa la sintaxis regular de event, el compilador genera el accessor por usted. Esto lo  hace claro que los eventos no son delegados, estos son convenientemente manejados como delegados.

Los delegados son ejecutados en un orden secuencial. Generalmente, los delegados son ejecutados en el orden en que fueron agregados, aunque  esto no es algo que es especifico dentro del Common Language Infraestructure (CLI), no debería depender de esto.

Una cosa que es un resultado directo del orden secuencial de ejecución es el manejo de las excepciones. Como en el siguiente ejemplo tenemos un suscriptor del event lanza un error.

using System;

namespace ExceptionWhenRaisingEvent
{
    public class Pub
    {
        public event EventHandler OnChange = delegate { };
        public void Raise()
        {
            OnChange(this, EventArgs.Empty);
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            CreateAndRaise();
        }

        public static void CreateAndRaise()
        {
            Pub p = new Pub();
            p.OnChange += (sender, e)
                => Console.WriteLine("Suscriptor 1 llamado");

            p.OnChange += (sender, e)
                => { throw new Exception(); };

            p.OnChange += (sender, e)
                => Console.WriteLine("Suscriptor 1 llamado");

            p.Raise();
        }
    }
}



Como puede ver, el primer subscriptor es ejecutado con éxito. el segundo lanza una excepción, y el tercero nunca es llamado.

Si este no es el comportamiento que usted quiere, necesita manualmente lanzar los eventos y manejar cualquier excepción que ocurra. Puede hacer esto usando el método GetInvocationList que es declarado en la clase base System.Delegate

El siguiente ejemplo obtiene los subscriptores y enumera manualmente.
using System;
using System.Collections.Generic;
using System.Linq;


namespace RaiseEventWhitExceptionManual
{
    public class Pub
    {
        public event EventHandler OnChange = delegate { };
        public void Raise()
        {
            var exceptions = new List<Exception>();
            foreach (Delegate handler in OnChange.GetInvocationList())
            {
                try
                {
                    handler.DynamicInvoke(this, EventArgs.Empty);
                }
                catch (Exception ex)
                {
                    exceptions.Add(ex);
                }
            }

            if (exceptions.Any())
            {
                throw new AggregateException(exceptions);
            }

        }

    }



    class Program
    {
        static void Main(string[] args)
        {
            CreateAndRaise();
        }

        public static void CreateAndRaise()
        {
            Pub p = new Pub();
            p.OnChange += (sender, e)
                => Console.WriteLine("Llamando al Subscriptor 1");

            p.OnChange += (sender, e)
                => { throw new Exception(); };

            p.OnChange += (sender, e)
                => Console.WriteLine("Llamando al Subscriptor 3");

            try
            {
                p.Raise();
            }
            catch (AggregateException ex)
            {
                Console.WriteLine(ex.InnerExceptions.Count);
            }

        }


    }
}
Resultado


Referencia:
Exam Ref 70-483 Programming in C#



C# using event Action delegate

Un popular patrón de diseño (una solución reusable para un problema recurrente) en el desarrollo de una aplicación es el publish-subscribe (editor-subscriptor). Usted subscribe a un evento y después lo notifica cuando el publisher de un evento lanza el nuevo evento. Este es usado para establecer bajo acoplamiento entre componentes es una aplicación.

Los delegados forman la base de un sistema basado en eventos en C#. El siguiente ejemplo presenta como una clase expone un delegado publico y como lanza a éste.

using System;

namespace UsingActionToExposeEvent
{
    public class Pub
    {
        public Action OnChange{get; set;}

        public void Raise()
        {
            if(OnChange != null)
            {
                OnChange();
            }
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            CreateAndRaise();
        }

        public static void CreateAndRaise()
        {
            Pub p = new Pub();
            p.OnChange += () => Console.WriteLine("Event raised to method 1");
            p.OnChange += () => Console.WriteLine("Event raised to method 2");

            p.Raise();

        }
    }
}

En este ejemplo, la clase Pub lanza el evento. Sin embargo, nada previene a usuarios esternos de la clase lanzar el evento. Tal y como llamamos a p.OnChange, cualquier usuario de la clase puede lanzar el evento para todos los subscriptores.

Para superar estas debilidades, C# usa la palabra clave event. El ejemplo anterior modifica la clase usando la sintaxis event.

using System;

namespace UsingActionToExposeEvent
{
    public class Pub
    {
        public event Action OnChange = delegate { };

        public void Raise()
        {
            if(OnChange != null)
            {
                OnChange();
            }
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            CreateAndRaise();
        }

        public static void CreateAndRaise()
        {
            Pub p = new Pub();
            p.OnChange += () => Console.WriteLine("Event raised to method 1");
            p.OnChange += () => Console.WriteLine("Event raised to method 2");

            p.Raise();

        }
    }
}

Usando la sintaxis event, hay un par de cambios interesantes. Primero usted deja de usar una propiedad publica pero a un campo publico. Normalmente, este podría ser un paso atras. Sin embargo con la sintaxis event, el compilador protege su campo de un acceso no deseado.

Un evento no puede ser directamente asignado por el operador (con el = en vez del +=). Así no puede tener el riesgo de que alguien remueva a todos los previos subscriptores, así con la sintaxis delegate.

Otro cambio es que los usuarios no externos pueden lanzar su evento. Este puede ser lanzado solamente por aquellos que son parte de la clase que define el evento.

El siguiente ejemplo usa una sintaxis especial par inicializar el evento como un delegado vacio. De esta forma, usted puede remover el nul alrededor del lanzador del evento porque puede ser cierto que el evento sea siempre nulo. Usuarios externos a su clase no pueden definir un valor para el evento nulo, usted puede con seguridad asumir que este siempre tenga un valor.

Hay sin embargo un cambio que debe mantener para seguir las convenciones de codificación den .NET Framework . En vez de usar el tipo Action para su evento, usted debería usar el EventHandler o EventHandler<T>. El EventHandler es declarado como en el siguiente ejemplo.

using System;

namespace CustomEventArguments
{
    public class MyArgs : EventArgs
    {
        public int Value { get; set; }

        public MyArgs(int value)
        {
            Value = value;
        }
    }

    public class Pub
    {
        public event EventHandler<MyArgs> OnChange = delegate { };
        public void Raise()
        {
            OnChange(this, new MyArgs(42));
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            CreateAndRaise();
        }

        public static void CreateAndRaise()
        {
            Pub p = new Pub();
            p.OnChange += (sender, e)
            => Console.WriteLine("Event raised: {0}", e.Value);

            p.Raise();
        }
    }
}

La clase Pub usa un EventHandler<MyArgs>, que especifican el tipo de argumentos event. Cuando se lanza este event, usted requiere pasar una instancia de MyAgrs. Suscribirse para el event puede acceder a los argumentos y usar a éste.

Aunque la implementación del event usa un campo publico, usted puede mantenerse en la construcción agregando y removiendo suscriptores. Este es llamado custom event accesor. El siguiente ejemplo crea un para un custom event accesor evento.

NOTA.
Observe de forma detenida  la declaración del delegado, tienen el mismo nombre pero la diferencia esta en que en la declaración del delegado la  primera letra es minúscula: onChange.
La declaración para el manejo del delegado la primera letra es mayúscula: OnChange y tiene el aspecto de una propiedad.

using System;

namespace CustomEventAccessor
{
    public class MyArgs : EventArgs
    {
        public int Value { get; set; }

        public MyArgs(int value)
        {
            Value = value;
        }
    }

    public class Pub
    {
        private event EventHandler<MyArgs> onChange = delegate { };
        public event EventHandler<MyArgs> OnChange
        {
            add
            {
                lock (onChange)
                {
                    onChange += value;
                }
            }

            remove
            {
                lock (onChange)
                {
                    onChange -= value;
                }
            }

        }

        public void Raise()
        {
            onChange(this, new MyArgs(42));
        }

    }


    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}



Un custom event accessor se observa como una propiedad con un accessor get. En vez de get y set usted usa add y remove. Es importante colocar un lock en los subscriptores para agregar y remover para hacer segura la operación en un hilo seguro.

Referencia:
Exam Ref. 70-384 Programming in C#










C# delegate, closure

Pensando en algo más complejo, por ejemplo cuando la función lambda hace referencia a variables declaradas fuera de la expresión lambda (o para la referencia this). Normalmente, cuando dejas al alcance de una variable, la variable no es valida. ¿Pero que si un delegado se refiere a una variable local y esta regresa después quien llamo al método? Ahora el delegado tiene una variable de larga vida. El compilador genera código que hace la vida de la variable sea más larga que la vida del delegado esto es llamado closure (cierre).

using System;

namespace UsandoDelegadoAction
{
    class Program
    {
        static void Main(string[] args)
        {
            int myVar = 100;

            Console.WriteLine("myVar antes de llamar a delegado {0}", myVar);

            Action<int, int> calc = (x, y) =>
            {
                //int myVar = 10;

                myVar += (x + y);
                Console.WriteLine("Llamada desde el delegado {0}", myVar);
            };

            calc(3, 4);
            Console.WriteLine("Despues de llamar al delegado {0}", myVar);
        }
    }
}




Si se intenta crear una variable local del mismo nombre a la variable externa, la ayuda inteligente de Visual Studio avisa que no se puede usar, como se ve en la siguiente imagen.



Reference:
Exam Ref. 70-483 Proramming in C#

C# using Action delegate

Algunas veces declaramos un delegado para un evento, sentimos un poco de incomodo de manejar. .NET Framework tiene uun par de tipos delegados preconstruidos que puede usar cuando declare  delegados. Por ejemplo:

public delegate int Calculate(int x, int y )

Es posible reemplazar delegate con un tipo pre-construido Fun<int, int, int>.  El tipo Fun<...> se encuentra en el espacio de nombre System y representa al delegado que regresa un tipo y puede tomar de 0 a16 parámetros. Todos estos tipos heredan desde System.MulticastDelegate asi usted puede agregar métodos para invocar la lista.

Si usted quiere un tipo delegado que no regrese un valor, puede usar el tipo System.Action. Estos pueden tomar de 0 a 16 parámetros, pero ellos no regresan valor un valor.

using System;

namespace UsandoDelegadoAction
{
    class Program
    {
        static void Main(string[] args)
        {
            Action<int, int> calc = (x, y) =>
            {
                Console.WriteLine(x + y);
            };

            calc(3, 4);

        }
    }
}

Referencia:
Exam Ref. 70-483 Programming in  C#





martes, 15 de diciembre de 2015

C# Using lambda expressions

Algunas veces la firma de un método puede tener más código que el solo cuerpo del método. Hay también situaciones en las que usted necesita un método completo solo para usar este en un delegado.

Para estos casos, Microsoft agrego algunas características a C#. En C# 2.0 los métodos anónimos. en C# 3.0, estos vienen a ser aun mejores usando lambda expressions. Las expresiones lambda son la forma preferida cuando se escribe nuevo código.

El siguiente  ejemplo:

using System;

namespace LambdaExpressionCreateDelegate
{
    class Program
    {
        public delegate int Calculate(int x, int y);  

        static void Main(string[] args)
        {
            Calculate calc = (x, y) => x + y;
            Console.WriteLine(calc(3, 4));  // presenta 7
            calc = (x, y) => x * y;
            Console.WriteLine(calc(3, 4)); // presenta 12

        }
    }
}

La expresión en ingles se usa go and goes y se lee: "x and y goes to adding x and y". Voy a realizar una lectura como se haría en un lenguaje cercano al de las matemáticas, se leeria así, "para toda y Yen la expresión se han de sumar y Y".

La función lambda no especifica nombre como los métodos. Es por eso las funciones lambda son llamadas anonymus fuctions (funciones anónimas) . No tiene que especificar un valor de return de forma explicita. El compilador infiere este de forma automática desde su expresión lambda. Y en el caso del ejemplo, los tipos de los parámetros  X y Y pueden no ser especificados de forma explicita.

Como lo puede ver una expresión lambda puede ser compacta. Si la expresión lambda tiene solamente un parámetro, usted puede aun remover los paréntesis alrededor de los parámetros.

Puede crear lambdas que abarquen múltiples declaraciones. Puede hacerlo agregando las llaves ( {} ) alrededor de las declaraciones que forman la lambda. Como en el siguiente ejemplo

using System;

namespace LambdaExpMultipleStatement
{
    class Program
    {
        public delegate int Calculate(int x, int y);

        public static Calculate calc =
            (x, y) =>
            {
                Console.WriteLine("Adding numbers");
                return x + y;
            };

        static void Main(string[] args)
        {
            Console.WriteLine("Resultado de expresion lambda {0} ", calc(3, 4));
        }
    }
}

Referencia:
Exam Ref. 70-483 Programming in C#


C# Delegates, GetInvocationList

Un evento puede ser usado para proporcionar notificaciones. NET Framework  ofrece tipos pre-construidos para crear eventos. Usando delegados, expresiones lambda y métodos anónimos, usted puede crear y usar eventos de manera confortable.

En C#, los delegados (delegates) son los bloques de construcción básicos para los eventos. Un delegado define la firma de un método. E C++, por ejemplo, se podría decir que es un apuntador  de función. En C# puede instanciar un delegado y permitir que apunte a otro método. Puede invocar el método a través del delegado.

using System;
using System.IO;
using System.Threading.Tasks;

namespace CovarianceWithDelegates
{
    public class MyDelegate
    {
        public delegate int Calculate(int x, int y);
        public int Add(int x, int y) { return x + y; }
        public int Multiply(int x, int y) { return x * y; }

        public void UseDelegate()
        {
            Calculate calc = Add;
            Console.WriteLine(calc(3, 4)); // presenta 7

            calc = Multiply;
            Console.WriteLine(calc(3, 4)); // presenta 12
        }

    }
    class Program
    {
     
        static void Main(string[] args)
        {
            MyDelegate del = new MyDelegate();

            del.UseDelegate();
                   
        }

    }
}

Otra característica de los delegados es que puede combinarlos. Esto se llama multicasting. Puede usar los operadores + o += para agregar otros métodos. Para invocar la lista de una instancia de un delegado existente, como se ve en el siguiente ejemplo.

using System;

namespace UsingMulticastDelegate
{
    public class MulticastDelegate
    {
        public void MethodOne()
        {
            Console.WriteLine("MethodOne");
        }

        public void MethodTwo()
        {
            Console.WriteLine("MethodTwo");
        }

        public delegate void Del();

        public void MultiCast()
        {
            Del d = MethodOne;
            d += MethodTwo;

            d();
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            MulticastDelegate mul = new MulticastDelegate();
            mul.MultiCast();
        }
    }
}

También es posible remover un método de la lista de invocación usando el operador de decrement (- o -=)

Todo esto es posible porque los delegados heredan desde la clase System.MulticastDelegate que a su vez hereda de System.Delegate. POr eso puede usar los miembros que son definidos en esta clase base en sus delegados.

Por ejemplo, para encontrar el número de métodos en un delegado multicast puede llamar a GetInvocationList().GetLength(0), como en el siguiente ejemplo.

using System;

namespace UsingMulticastDelegate
{
    public class MulticastDelegate
    {
        
        public void MethodOne()
        {
            Console.WriteLine("MethodOne");
        }

        public void MethodTwo()
        {
            Console.WriteLine("MethodTwo");
        }

        public delegate void Del();
        Del d;

        public void MultiCast()
        {
            d = MethodOne;
            d += MethodTwo;

            d();
            
        }

        public int GetLengthDelegate()
        {
            return d.GetInvocationList().GetLength(0);
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            MulticastDelegate mul = new MulticastDelegate();
            mul.MultiCast();

            Console.WriteLine("GetInvocationList().GetLength(0) = {0}",
                mul.GetLengthDelegate());
        }
    }
}

Referencia:
Exam Ref 70-483 Programming in C#





C# ConcurrentBag

Una colección ConcurrentBag es una gran bolsa de elementos. Esto permite duplicar y no tiene un orden particular. Metodos importantes son Add, TryTake y TryPeek.

using System;
using System.Collections.Concurrent;

namespace UsingConcurrentBag
{
    class Program
    {
        static void Main(string[] args)
        {
            ConcurrentBag<int> bag = new ConcurrentBag<int>();

            bag.Add(42);
            bag.Add(21);

            int result;
            if (bag.TryTake(out result))
                Console.WriteLine(result);

            if (bag.TryPeek(out result))
                Console.WriteLine("There is a next item: {0} ", result);

        }
    }
}

Una cosa para mantener en mene es que el método TryPeek no es muy util en un medio ambiente de multihilos. Este podría ser otro hilo remueve el elemento  antes de que usted puede acceder a este.

ConcurrentBag también implementa IEnumerable<T>, asi que usted puede interinar sobre este. Esta operación es hecho como un hilo seguro haciendo una imagen de la colección cuando inicia iterar en esta,  asi los elementos agregados a la colección después de iniciar la iteración este no sería visible, como se ve en el siguiente ejemplo.

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace EnumeratingConcurrentBag
{
    class Program
    {
        static void Main(string[] args)
        {
            ConcurrentBag<int> bag = new ConcurrentBag<int>();
            Task.Run(() => 
            {
                bag.Add(42);
                Thread.Sleep(10000);
                bag.Add(21);
            });

            Task.Run(() => 
            {
                foreach (int i in bag)
                    Console.WriteLine(i);
            }).Wait();
        }
    }
}

NOTA
En el ejemplo de la referencia el valor era de 1000 milisegundos y de esa forma el resultado no se presentaba como el libro menciona y el valor se coloco como: 10,000

El código despliega 42 porque el otro valor es agregado después de iterar sobre la bolsa que ha iniciado.

Referencia:
Exam Ref. 70-483 Programming in C#




C# BlockingCollection CompleteAdding

En el uso de BlockingCollection es posible utilizar el método CompleteAdding para señalarle que no hay más elementos que agregar. Si otros hilos esta esperando por nuevos elementos, estos no bloquearan a ninguno.

En el siguiente ejemplo se ha removido el siclo While. Usando GetCosumingEnumerable, usted obtiene un IEnumerable que bloquea hasta encontrar un nuevo elemento. De esta forma, usted puede usar foreach con su  BlockingCollection  para enumerar este.

using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;

namespace UsandoGetConsumingEnumerable
{
    class Program
    {
        static void Main(string[] args)
        {
            BlockingCollection<string> col = new BlockingCollection<string>();
                       
            Task read = Task.Run(() =>
            {
                foreach (string v in col.GetConsumingEnumerable())
                    Console.WriteLine(v);
            });

            Task write = Task.Run(() =>
            {
                while (true)
                {
                    string s = Console.ReadLine();
                    if (string.IsNullOrWhiteSpace(s)) break;
                    col.Add(s);
                }
            });

            write.Wait();
        }
    }
}

Referencia:
Exam Ref 70-483 Programming in C#

lunes, 14 de diciembre de 2015

C# Concurrent Collections BlockingCollection

Cuando se trabaja en un ambiente de multihilos. necesita asegurarse de que no esta manipulando datos compartidos al mismo tiempo sin sincronizar el acceso.

.NET Framework ofrece algunas clases de colección que son creadas especificamente para ser usadas en ambientes medioambientes concurrentes como los que se producen cuando se usan lultihilos. estas colecciones ofrecen un ambiente un hilo seguro, lo que significa que internamente usan sincronizacion para hacer seguro el acceso por multiples hilos al mismo tiempo. Las colecciones son :

BlockingCollection<T>
ConcurrentBag<T>
ConcurrentDictionary<TKey, T>
ConcurrentQueue<T>
ConcurrentStack<T>

BlockingCollection<T>
Esta colleccion es un hilo seguro para agregar y remover datos. Remover un elemento desde la coleccion puede ser bloqueada hasta que los datos esten disponibles. Agregar datos es rápido, pero asignar datos puede alcanzar un limite. Si este limite es alcanzado un bloque de elementos lallamada al hilo es realizada hasta se encuentre espacio.

BlockingCollection es en realidad un envoltorio alrededor de otro tipo de colecciones. Si usted no da una alguna instruccion especifica este usa por omision ConcurrentQueue.

Una colección regular levanta un escenario multihilos porque el elemento puede ser removido por otro hilo mientras  el otro hilo estra tratando de leer este.

El siguiente ejemplo usa una coleccion BlockingCollection. Una Task esta preparada para nuevos elementos agregados a la colección. Este bloque es caso de no haber disponibles. La otra tarea agrega elementos a la colección.


using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;

namespace UsandoBlockingCollection
{
    class Program
    {
        static void Main(string[] args)
        {
            BlockingCollection<string> col = new BlockingCollection<string>();
            Task read = Task.Run(() =>
            {
                while (true)
                {
                    Console.WriteLine(col.Take());
                }
            });

            Task write = Task.Run(() =>
            {
                while (true)
                {
                    string s = Console.ReadLine();
                    if (string.IsNullOrWhiteSpace(s)) break;
                    col.Add(s);
                }
            });

            write.Wait();
        }
    }
}

El programa termina cuando el usuario solo hace ENTER, sin dato. Hasta que, cualquier cadena es colocada es agregada por el Task que escribe y removido por la Task read.




Referencia:
Exam Ref 70-483 Programming in C#




domingo, 13 de diciembre de 2015

C# PLINQ ForAll

Cuando usamos PLINQ, puede usar el operador ForAll para iterar sobre una colección cuando la interacción puede también ser realizada en forma paralela, como se ve en el siguiente ejemplo.

using System;
using System.Linq;

namespace Capitulo1
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = Enumerable.Range(0, 20);
            var parallelResult = numbers.AsParallel()
                .Where(i => i % 2 == 0);

            parallelResult.ForAll(e => Console.WriteLine(e));
        }
    }
}

En contraste con foreach, ForAll no necesita todos los resultados antes de iniciar la ejecución. En este ejemplo, ForAll remueve cualquier orden previamente especificado.


Referencia:
Exam Ref 70-483 Programming in C#


C# PLINQ, AsOrdered, AsSequential

Al ejecutar consultas en paralelo es necesario recordar que el proceso no garantiza un orden en particular, como se ve puede observar con el siguiente ejemplo.

using System;
using System.Linq;

namespace MakingParallelQuerySequential
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = Enumerable.Range(0, 20);
            var parallelResult = numbers.AsParallel()
                .Where(i => i % 2 == 0);

            // con Take, usted define cuantos resultados desea obtener
            foreach (int i in parallelResult.Take(5)) Console.WriteLine(i);
    
        }
    }
}

Al ejecutar puede ver el resultado de la consulta, la cual no se encuentra en un orden en particular. El resultado del código depende los recursos disponibles del CPU. Si usted quiere asegurar de que los resultados se encuentren ordenados use el operador AsOrdered. El proceso se ejecuta de forma paralela, pero el resultado es colocado en un buffer y ordenado. Como se ve en el siguiente ejemplo.

using System;
using System.Linq;

namespace MakingParallelQuerySequential
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = Enumerable.Range(0, 20);
            var parallelResult = numbers.AsParallel().AsOrdered()
                .Where(i => i % 2 == 0);

            // con Take, usted define cuantos resultados desea obtener
            foreach (int i in parallelResult.Take(5)) Console.WriteLine(i);

        }
    }
}


Si usted tiene una consulta compleja que pueda beneficiarse del procesamiento en paralelo pero tiene algunas partes que deberían ser realizados en forma secuencia, puede usar AsSequential.

using System;
using System.Linq;

namespace MakingParallelQuerySequential
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = Enumerable.Range(0, 20);
            var parallelResult = numbers.AsParallel().AsOrdered()
                .Where(i => i % 2 == 0).AsSequential();

            // con Take, usted define cuantos resultados desea obtener
            foreach (int i in parallelResult.Take(5)) Console.WriteLine(i);

        }
    }
}

Referencia:
Exam Ref 70-483 Programming in C#








C# PLINQ WithExecutionMode

El runtime determina si la consulta requiere un  proceso paralelo. Cuando hacemos esto, este genera un objeto Task y inicia la ejecución de este. Si usted quiere forzar PLINQ dentro de una consulta paralela, puede usar el método WithExecutionMode y especificar que la consulta debería ejecutar en un proceso paralelo.

using System;
using System.Linq;

namespace MakingParallelQuerySequential
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = Enumerable.Range(0, 50);
            var parallelResult = numbers.AsParallel()
                .WithExecutionMode(ParallelExecutionMode.ForceParallelism)
                .Where(i => i % 2 == 0).AsSequential();

            foreach (int i in parallelResult.Take(5)) Console.WriteLine(i);

        }
    }
}

PLINQ esta diseñado para explotar las facultades del paralelismo. Sin embargo no todas las consultas se benefician de la ejecución en paralelo. Por ejemplo, cuando una consulta contiene un solo delegado que hace un trabajo muy pequeño, la consulta podría ejecutarse más rápidamente de forma secuencial. Esto es porque la sobrecarga inherente a la ejecución en paralelo requiere más recursos que la consulta simple. Es por eso que PLINQ no hace de forma automática cualquier consulta. PLINQ examina primero la estructura de la consulta y los operadores que este contiene. Basado en este análisis, PLINQ usa por omisión el modo de ejecución default,  podría decidir ejecutar algo o todo la consulta de forma secuencial. Sin embargo, en algunos casos usted podría conocer mas de la consulta que lo que PLINQ pueda determinar desde su análisis. Por ejemplo, usted podría saber que el delegado requiere más recursos, y que la consulta se puede beneficiar del proceso en paralelo. En este caso use el método WithExecutionMode<TSource> y especificar el valor ForceParallelism para instruir a PLINQ a que siempre ejecute la consulta en forma paralela.

Referencia:
Exam Ref 70-483 Programming in C#
https://msdn.microsoft.com/en-us/library/dd547138(v=vs.110).aspx


C# PLINQ WithDegreeOfParallelism

Usted puede limitar la cantidad de paralelismo utilizado usando el método WithDegreeOfParallelism. Usted pasa al metodo un entero que representa el número de procesadores que usted quiere usar. Normalmente, PLINQ usa todos los procesadores (hasta 64) pero puede limitar con este método los que usted quiere usar.

using System;
using System.Linq;

namespace MakingParallelQuerySequential
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = Enumerable.Range(0, 50);
            var parallelResult = numbers.AsParallel()
                .WithExecutionMode(ParallelExecutionMode.ForceParallelism)
                .WithDegreeOfParallelism(2)
                .Where(i => i % 2 == 0).AsSequential();

            foreach (int i in parallelResult.Take(5)) Console.WriteLine(i);

        }
    }
}

C# PLINQ AsParallel

Language-Integrated Query(LINQ) es un adicción al lenguaje C#. Usted puede usar este lenguaje para ejecutar consultas sobre todos los tipos de datos.

Parallel Language-Integrated Query (PLINQ) puede ser usado en objetos que potencialmente puedan turnar su proceso en una consulta secuencial en un proceso paralelo.

Los métodos extendidos para usar PLINQ están definidos en la clase System.LinqParallelEnumerable. Las versiones Parallel de los operadores de LINQ, como Where, Select, SelectMany, GroupBy, Join, OrderBy, Skip y Take, se pueden usar como las versiones de LINQ.

using System;
using System.Linq;

namespace UsingAsParallel
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = Enumerable.Range(0, 100);
            var parallelResult = numbers.AsParallel()
                .Where(i => i % 2 == 0)
                .ToArray();

            foreach (int i in parallelResult)
            {
                Console.WriteLine(i);
            }

        }
    }
}


sábado, 12 de diciembre de 2015

C# ConfigureAwait

En este ejemplo se usa una aplicación WPF para explicar el uso de ConfigureAwait, el ejemplo lanza una excepción: la linea Output.Content = content no es ejecutado en  el hilo de la UI porque el método ConfigureAwait(false). Observe el ejemplo.


using System.Windows;
using System.Net.Http;

namespace ConfigureAwait
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void button_Click(object sender, RoutedEventArgs e)
        {
            HttpClient httpClient = new HttpClient();

            string content = await httpClient
                .GetStringAsync("http://www.microsoft.com")
                .ConfigureAwait(false);

            Output.Content = content;
        }
    }
}

Mientras ocurre esto usted puede desear ejecuta otra tarea,  como escribir el contenido a un archivo, uno necesita definir un valor para SynchronizationContext.

using System.IO;
using System.Text;
using System.Windows;
using System.Net.Http;

namespace ConfigureAwait
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void button_Click(object sender, RoutedEventArgs e)
        {
            HttpClient httpClient = new HttpClient();

            string content = await httpClient
                .GetStringAsync("http://www.microsoft.com")
                .ConfigureAwait(false);
            
            using (FileStream sourceStream = new FileStream("temp.html",
                FileMode.Create, FileAccess.Write, FileShare.None,
                4096, useAsync: true))
            {
                byte[] encodedText = Encoding.Unicode.GetBytes(content);
                await sourceStream.WriteAsync(encodedText, 0, encodedText.Length)
                    .ConfigureAwait(false);
            }
        }
    }
}

Ambos await usan el método Configure.Await(false) porque hay verificación entre los métodos para observar aquel que hubiera terminado,  así que el código del hilo de la UI  permanece corriendo. 

Cuando creamos métodos asíncronos, es importante elegir el tipo de retorno de Task o Task<T>. Evite el tipo de retorno void. Un tipo void de retorno de un método async es efectivamente un método de tipo dispara y olvida. Usted pudiera no querer inspeccionar el tipo de retorno, y usted no puede ver si una excepción hubiera ocurrido. Usted debería usar métodos async void solamente cuando trate con eventos asíncronos.

El uso de las palabras clave asyn/await hace mucho más facíl escribir código asíncrono. En el mundo de ahora con múltiples núcleos y requerimientos para que las aplicaciones permanezcan receptivas y escalables, es importante mirar las posibilidades de usar estas nuevas palabras claves para mejorar sus aplicaciones.


viernes, 11 de diciembre de 2015

Hilos en C#, ParallelLoopState

Es posible cancelar un loop de proceso paralelo usando el objeto ParallelLoopState. Se tienen dos opciones para hacer esto: Break o Stop,

Break asegura que todas las interacciones que se encuentren en ejecución terminan. Stop termina cualquier cosa que este ejecutándose. Ejemplo:

Cuando se rompe un ciclo paralelo, el resultado del valor de la variable isCompleted es false y la variable LowestBreakItereation de 50. Cuando se usa el método Stop, la variable LowestBreakItereation es null.

using System;
using System.Threading.Tasks;

namespace UsandoParallelBreak
{
    class Program
    {
        static void Main(string[] args)
        {

            ParallelLoopResult result = Parallel.
                For(0, 100, (int i, ParallelLoopState loopState) =>
                {
                    Console.WriteLine("proceso paralelo {0}", i);

                    if (i == 50)
                    {
                        Console.WriteLine("Breaking loop");
                        loopState.Break();
                    }

                    return;

                });

        }
    }
}

Hilos en C#, Parallel.For... Foreach

El espacio de nombres System.Threading.Task contiene otra clase que puede ser usado para proceso en paralelo. La clase Parallel tiene un par de métodos estáticos -For, ForEach, Invoke - que usted puede usar para hacer trabajo en paralelo.

El paralelismo significa tomar una cierta tarea y dividir esta en un conjunto de tareas relacionadas que pueden ser ejecutadas simultáneamente. No debería sustituir los ciclos de su código por ciclos paralelos. Si tiene que realizar tareas que no sean secuenciales, puede usar la clase Parallel .

Incrementar el funcionamiento con proceso paralelo ocurre solamente cuando tenga un gran conjunto de trabajo para ser realizado y que puede ser realizado en paralelo. Para pequeños conjuntos de trabajo o para trabajo que requiera acceso a recursos de forma sincronizada, usar la clase Parallel  tienen efectos que degradan el funcionamiento.

La mejor forma de saber si debería usar trabajo en paralelo es medir los resultados. Los siguientes ejemplos usan Parallel.For y Parallel.ForEach.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace UsandoParallelFor
{
    class Program
    {
        static void Main(string[] args)
        {
            Parallel.For(0, 10, i => 
            {
                Console.WriteLine("Ejecución en paralelo : {0} ", i);
                Thread.Sleep(1000);
            });

            Console.WriteLine("Fin de ejecución en paralelo.");

        }
    }

}



using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace UsandoParallelFor
{
    class Program
    {
        static void Main(string[] args)
        {
            var numbers = Enumerable.Range(0, 10);
            Parallel.ForEach(numbers, i =>
            {
                Console.WriteLine("Ejecución en paralelo : {0} ", i);
                Thread.Sleep(1000);
            });

        }
    }
}



Hilos en C#, WaitAll

Es posible utilizar el método WaitAll de la clase Task para esperar a que terminen múltiples tareas antes de continuar la ejecución de la tarea primaria, como se ve en el siguiente ejemplo:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace UsandoTaskWaitAll
{
    class Program
    {
        static void Main(string[] args)
        {
            Task[] tasks = new Task[3];

            tasks[0] = Task.Run(()=> 
            {
                Thread.Sleep(1000);
                Console.WriteLine("1");
                return 1;
            });

            tasks[1] = Task.Run(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("2");
                return 1;
            });

            tasks[2] = Task.Run(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("3");
                return 1;
            });

            Task.WaitAll(tasks);

        }
    }
}

Referencia:
Exam Ref 70-483 Programming in C#

jueves, 10 de diciembre de 2015

Hilos en C# ContinueWith overloads

El método ContinueWith tiene un par de métodos sobrecargados que puede usar para configurar la continuación de la ejecución. De esta forma puede agregar diferentes métodos de continuación cuando ocurra una excepción, como por ejemplo cuando la tarea deba ser cancelada o completada con éxito.

Nota:
Debe notar el uso del espacio de nombres System.Threading.Tasks.

using System;
using System.Threading.Tasks;

namespace UsingTaskReturnValue
{
    class Program
    {
        static void Main(string[] args)
        {
            Task<int> tarea = Task.Run(() =>
            {
                return 25;
            });

            tarea.ContinueWith((i) =>
            {
                Console.WriteLine("Cancelado");
            }, TaskContinuationOptions.OnlyOnCanceled);

            tarea.ContinueWith((i) =>
            {
                Console.WriteLine("Falla o defecto");
            }, TaskContinuationOptions.OnlyOnFaulted);

            var tareaCompletada = tarea.ContinueWith((i) =>
            {
                Console.WriteLine("Completado");
            }, TaskContinuationOptions.OnlyOnRanToCompletion);

            tareaCompletada.Wait();

        }
    }
}

Referencia:
Exam Ref 70-483 Programming in C#


Hilos en en C#, Threads, ContinueWith

Por la propia naturaleza de la orientación a objetos del objeto Task, una cosa que puede hacer es agregar una tarea de continuación. Esto significa que usted podría querer hacer otra operación tan pronto la Task termine, utilizando ContinueWith.

Ejemplo.

using System;
using System.Threading.Tasks;

namespace UsingTaskReturnValue
{
    class Program
    {
        static void Main(string[] args)
        {
            Task<string> tarea = Task.Run(() =>
            {
                return "Hilo regresando un valor";
            }).ContinueWith((i) => 
            {
                return i.Result + "... Continua la ejecución.";
            } );

            Console.WriteLine(tarea.Result); // presenta
        }
    }
}

Referencia:
Exam Ref 70-483 Programming in C#





miércoles, 9 de diciembre de 2015

Hilos con C#, Tasks, Task -T-

Colocar un trabajo en una cola de hilos puede ser util pero tiene algunos defectos. No hay una forma pre-construida que permita conocer cuando la operación a terminado  y cuando ésta ha regresado un valor.

.NET Framework introduce el concepto de Task, que es un objeto que representa algún trabajo que debería ser realizado. El objeto Task puede decirle si el trabajo a sido completado y si la operación a regresado un resultado.

Un task scheduler es responsable de iniciar y manejar al objeto Task. Por omisión el programador de tareas usa hilos desde el pool de hilos para ejecutar la tarea Task.

Las tareas pueden ser usadas para hacer o mantener su aplicación receptiva. Si el hilo que administra la interfaz del usuario descarga el trabajo en otro hilo desde el pool de hilos, este puede mantener procesando eventos de usuario y asegurar que la aplicación puede permanecer en uso. Pero esto no le ayuda con la escalabilidad. Si un hilo recibe una solicitud web, este podría iniciar una nueva tarea, este podría consumir otro hilo desde el pool de hilos mientras que espera resultados.

Ejecutar una tarea Task en otro hilo permite mantener receptiva la aplicación de usuario. Misma que puede ser manejada en otro hilo, o bien hacer paralelo su trabajo en múltiples procesadores.

Ejemplo de como iniciar una nueva tarea Task y esperar hasta que esta termine. En este ejemplo se crea una tarea que inicia de inmediato. La llamada a Wait es equivalente al uso de Join. Este espera hasta que la tarea Task es finalizada antes de salir de la aplicación.

using System;
using System.Threading.Tasks;

namespace StartingNewTask
{
    class Program
    {
        static void Main(string[] args)
        {
            Task tarea = Task.Run( () => 
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("Tarea en ejecución {0}", i);
                }
            } );

            tarea.Wait();
        }
    }
}

Además de Task, el .NET Framework tambien tiene una clase Task<T> que es posible utilizar cuando deba regresar un valor, como se ve en el siguiente ejemplo.

using System;
using System.Threading.Tasks;

namespace UsingTaskReturnValue
{
    class Program
    {
        static void Main(string[] args)
        {
            Task<string> tarea = Task.Run(() => { return "Hilo regresando un valor"; });

            Console.WriteLine(tarea.Result); // presenta
        }
    }
}


Intentar leer la propiedad Result en una tarea forzará al hilo a intentar leer el resultado esperando    que la tarea sea terminada antes de continuar. Mientras la tarea no sea terminada es imposible dar el resultado. Si la tarea no esta finalizada, este llamará el bloque del hilo en curso.


Referencia:
Exam Ref 70-483 Programming in C#

Hilos con C#, Threads pools

Al trabajar directamente con la clase Thread, se crean y se matan los hilos cuando estos terminan de usarse.

Un pool (grupo) de hilos es creado para rehusar estos hilos, similar a la forma en que se usan las conexiones de base de datos. En lugar de intentar matar un hilo, este se envía al pool donde este puede ser reusado si se presenta una solicitud de un hilo.

Al trabajar con un pool de hilos de.NET, coloca en cola los elementos de trabajo donde son recolectados por los hilos disponibles desde el pool. En el siguiente ejemplo puede verse como trabaja el pool.

using System;
using System.Threading;

namespace ThreadPools
{
    class Program
    {
        static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem((s) => 
            {
                //Console.WriteLine("Trabajando en un hilo desde el pool de hilos... {0} ", s.ToString());
                Console.WriteLine("Trabajando en un hilo desde el pool de hilos");
            });
            Console.ReadLine();

        }
    }
}

El pool de hilos limita el numero de hilos y puede obtenerse menos grado de paralelismo que al usar la clase Thread. Pero el pool de hilos tiene muchas ventajas.

Por ejemplo un servicio Web responde a una solicitud. Todos estas solicitudes vienen en tiempo y forma desconocida. El pool de hilos se asegura de que cada solicitud sea agregada a la cola, esto asegura que su servidor no se vea rebasado por la cantidad de solicitudes. Si usted crea hilos manualmente, usted puede fácilmente agotar al servidor.

Cada solicitud tienen características únicas en el trabajo que este necesita realizar. El pool de hilos es mapeado y este trabaja con los hilos disponible en el sistema.

El pool de hilos automáticamente maneja la cantidad de hilos necesarios. Cuando este es creado inicia vacío. Cuando una solicitud viene, este crea hilos adicionales para manejar estas solicitudes. El Tiempo de trabajo del hilo puede ser tan largo como sea necesario hasta terminar una operación, y seguir manejando las nuevas solicitudes que se manejaran por los hilos.

Para más información  del pool de hilos
http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx.


Referencias:
Exam Ref 70-483 Programming in C#




Hilos con C# (Threads) , ThreadLocal

Si usted quiere usar datos locales en un hilo y que estos se inicialicen para cada hilo se debe usar la clase ThreadLocal<T>. Esta clase toma un delegado para un método que inicializa el valor.

En el siguiente ejemplo puede ver otra de las características del .NET Framework. Puede usar la clase ThreadCurrentThread para buscar información acerca del hilo que se encuentra en ejecución, lo que se conoce como execution context. Esta propiedad le permite acceder a propiedades como:

  • La current culture, CultureInfo asociado al hilo es usado para el formato de fechas, convenciones de casing y comparación de cadenas. 
  • principal (que representa el contexto de seguridad en uso)
  • priority, el valor que indica como el hilo debería ser programado por el sistema operativo.

Cuando un hilo es creado, el motor de ejecución asegura que el contexto de ejecución del hilo principal se propague al nuevo hilo. De esta forma el nuevo hilo tiene los mismos privilegios que el hilo principal.

La copia de los datos tiene un costo sobre los recursos, sin embargo, si usted no necesita estos datos, puede deshabilitar este comportamiento usando el método ExecutionContext.SuppressFlow.

Ejemplo.

using System;
using System.Threading;

namespace UsingThreadLocal
{
    class Program
    {
        public static ThreadLocal<int> _variableHiloLocal =
            new ThreadLocal<int>(() => 
            {
                return Thread.CurrentThread.ManagedThreadId;
            });

        static void Main(string[] args)
        {

            new Thread(() => 
            {

                Console.WriteLine("Valor de _variableHiloLocal para hilo A {0}", _variableHiloLocal.Value);

                for (int i = 0; i < _variableHiloLocal.Value; i++)
                {
                    Console.WriteLine("Primer hilo A: {0}", i);
                }
            }).Start();

            new Thread(() =>
            {
                Console.WriteLine("Valor de _variableHiloLocal para hilo B {0}", _variableHiloLocal.Value);

                for (int i = 0; i < _variableHiloLocal.Value; i++)
                {
                    Console.WriteLine("Segundo hilo B: {0}", i);
                }
            }).Start();

            Console.ReadKey();


        }
    }
}

Ejemplo de resultado:



Referencias:
Exam Ref 70-483 Programming in C#

Referencias Internet:
https://msdn.microsoft.com/en-us/library/dd642243(v=vs.110).aspx