Robotics 2

Continuamos con Robotics, como habíamos comentado en el post anterior, con CCR podemos ejecutar tareas de manera concurrente, esta tareas normalmente van a ser el procesamiento de los valores que el robot nos devuelve a través de la clase Port<T>.

Vimos unos ejemplos de cómo trabajar con CCR, ahora continuamos con algún ejemplo más complejo.

void RunFromIterator()
{
    Dispatcher d = new Dispatcher(0, "Test Pool");

    DispatcherQueue taskQ = new DispatcherQueue("Test Queue", d);

    Console.WriteLine("Before Iterator submitted - thread {0}", Thread.CurrentThread.ManagedThreadId);

    Arbiter.Activate(taskQ,
        
        Arbiter.FromIteratorHandler(IteratorExample),
        Arbiter.FromIteratorHandler(IteratorExample),
        Arbiter.FromIteratorHandler(IteratorExample),
        Arbiter.FromIteratorHandler(IteratorExample)
        );

    Console.WriteLine("After Iterator submitted - thread {0}", Thread.CurrentThread.ManagedThreadId);

}

private static IEnumerator<ITask> IteratorExample()
{
    Port<int> p1 = new Port<int>();
    Port<int> p2 = new Port<int>();

    p1.Post(0);

    bool done = false;

    while (!done)
    {
        yield return Arbiter.Receive(false, p1,
            delegate(int i)
            {
                Console.WriteLine("P1 Thread {0}: {1}", Thread.CurrentThread.ManagedThreadId, i);
                p2.Post(i + 1);
            }
        );

        yield return Arbiter.Receive(false, p2,
            delegate(int i)
            {
                Console.WriteLine("P2 Thread {0}: {1}", Thread.CurrentThread.ManagedThreadId, i);
                if (i >= 10000000000)
                    done = true;
                else
                    p1.Post(i + 1);
            }
        );
    }

    yield break;
}

Si nos fijamos en este ejemplo nuestro Arbiter activa cuatro tareas que las genera a través de un método helper que se llama, Activator.FromIteratorHandler que básicamente es un delegado a un método del tipo:

IEnumerable<ITask> GetMethod();

Si nos fijamos en este método lo que devuelve es un IEnumerable<ITask>, ITask era la interface que teníamos que implementar para hacer una tarea que se ejecutase en el Dispatcher de CCR, así que de alguna manera estamos devolviendo una colección de tareas para que el Dispatcher las ejecute. Si nos fijamos en el código que tenemos en el cuerpo de la función, hacemos cosas como esta.

yield return Arbiter.Receive

Al utilizar la palabra reservada yield, estamos indicando que vamos a devolver un ITask, que lo provee Arbier.Receive, a ese enumerador infinito que tenemos. Y digo enumerado infinito porque en principio no sabemos cuando vamos a terminar de enumerar esta colección. Yield se utiliza cuando estamos haciendo la implementación de un IEnumerable y de base tenemos un array o una lista y devolvemos elemento a elemento. En este caso es algo parecido, solo que no tenemos una colección de base sino que tenemos la flexibilidad de decidir cuando ese enumerado termina. ¿Y cuando termina?, pues cuando se devuelve un yield break;.

¿Por qué se usa yield y IEnumerable<ITask>?, pues tiene que ver de nuevo con la concurrencia. Teniendo en mente lo que anteriormente dije sobre como CCR está implementado, el uso de yield hace que de alguna manera cuando el DispatcherQueue recorra esa lista por nostros, nostros en nuestro código seamos capaces de devolver esa tarea para que se ejecute en el Dispatcher y aunque salimos del cuerpo del método, el uso de yield haga que de alguna manera se acuerde de cuales eran los valores que teníamos antes en nuestro método y que todo eso sea gestionado por el Dispatcher.

Es desde luego una solución muy elegante a un problema de enumeración de tareas que no sean bloqueadas por el llamado y el que llama.

Uno después de ver este codigo se da un poco cuenta de la importancia que tiene ese procesamiento de colas dentro de CCR, y como Robotics hace uso de esto. Extendiendo un poco el tema de las colas, CCR introduce el conceto de PortSet. PortSet, que como su nombre indica, es un grupo de puertos, perite asociar varios tipos de datos para hacer puertos. Podemos hacer un PortSet de 20 tipos en .NET Framework y 8 tipos de CF. Por supuesto esta clase se usa con genericidad.

PortSet<string,int,int,double> portSet;

Esto permite aumentar las opciones de las que podemos hacer con una cola. Por ejemplo con Arbiter ahora podemos hacer lo siguiente:

void Choice()
{
    PortSet<bool, int> ps = new PortSet<bool, int>();

    
    Activate(
        Arbiter.Choice<bool, int>(ps,
            delegate(bool b)
            { Console.WriteLine("Choice: " + b.ToString()); },
            delegate(int n)
            { Console.WriteLine("Choice: " + n.ToString()); }
        )
    );

   
    ps.Post(1000000);
    ps.Post(true);
    ps.PostUnknownType(true);
    ps.PostUnknownType("asdad");
}

Si nos fijamos en el ejemplo, tenemos una activación de un PortSet, pero ahora indicamos dos tipos de Handler<T> para cada uno de los tipos que define nuestro PortSet, esto permite discrimiar el consumo de los valores del puerto a través de tu tipo. Al final de ejemplo podemos ver como tenemos para cada tipo una sobrecarga de Post(T value) y un método llamado PostUnknownType(object) que permite que posteemos un mensaje en ese grupo de puertos. En caso de que el tipo no se pueda resolver, en este caso string, se lanzará una excepción.

Tambien podemos hacer Join con los PortSet sentencias lógicas AND, veamos.

void Join()
{
    Port<bool> p1 = new Port<bool>();
    Port<int> p2 = new Port<int>();
    Port<string> p3 = new Port<string>();

    Arbiter.Activate(Environment.TaskQueue,
        Arbiter.JoinedReceive(
            false, p1, p2,
            delegate(bool b, int i)
            {
                Console.WriteLine("Join 1: {0} {1}", b, i);
                p2.Post(i + 1);
            }
        )
    );

     Arbiter.Activate(Environment.TaskQueue,
        Arbiter.JoinedReceive(
            false, p2, p3,
            delegate(int i, string s)
            {
                Console.WriteLine("Join 2: {0} {1}", i, s);
                p2.Post(i - 1);
            }
        )
    );

    p1.Post(true);
    p3.Post("hello");
    p2.Post(99);
}

En el que hasta que no se recivan dos valores en el puerto del tipo especificado no se van a llamar al método que los procese.

Expandiendo este conecpto podemos en vez de esperar un valor único que procesar, esperar una lista de valores de tamaño fijo (un array).

Port<int> p = new Port<int>();

Arbiter.Activate(Environment.TaskQueue,
   Arbiter.MultipleItemReceive(
       true, p, 6,
       delegate(int[] array)
       {
           string s = "";
           for (int i = 0; i < array.Length; i++)
               s += array[i].ToString() + " ";
           Console.WriteLine("{0} Items: {1}", array.Length, s);
       }
   )
);

En este ejemplo hasta que no se reciben 6 elementos no se procesan, y por supuesto se procesan todos a la vez.

También podemos tener multiples procesadores, para varios tipos de datos.

PortSet<int, double> pSet = new PortSet<int, double>();

Activate(
    Arbiter.MultipleItemReceive(
        pSet, 10,
        delegate(ICollection<int> colInts, ICollection<double> colDoubles)
        {
            Console.Write("Ints: ");
            foreach (int i in colInts)
                Console.Write(i + " ");
            Console.WriteLine();
            Console.Write("Doubles: ");
            foreach (double d in colDoubles)
                Console.Write("{0:F2} ", d);
            Console.WriteLine();
        }
    )
);

En el que hasta que no se reciban 10 valores, como mínimo, en los dos puertos no se ejecutará el método que los procesará.

Y ya para terminar esta breve pero intensa introducción a CCR, hablaremos de las casualidades. Las casualidades no son más que una manera que tiene el CCR de llamar a las excecpiones que se produzcan en nuestro código. Hay que tener en cuenta que en cualquier momento se puede lanzar una excepción y que tenemos que ser capaces de procesarla y que no haga que el codigo se rompa.

private void Causality()
{
    using (Dispatcher d = new Dispatcher())
    {
        using (DispatcherQueue taskQ = new DispatcherQueue("Causality Queue", d))
        {
            Port<Exception> ep = new Port<Exception>();
            Port<int> p = new Port<int>();

            Dispatcher.AddCausality(new Causality("Test", ep));

            Console.WriteLine("Main thread: {0}", Thread.CurrentThread.ManagedThreadId);

            Arbiter.Activate(taskQ, Arbiter.Receive(false, p, CausalityExample));

            p.Post(2);
            Wait(500);

            Exception e;
            while (ep.Test(out e))
                Console.WriteLine("Exception: " + e.Message);
        }
    }
}

Básicamente las casualidades son un Port<T> de excepciones en los que se van posteando automáticamente todas las excepciones que se producen en el código para después procesarlos.

Este último ejemplo también muestra un método Test que nos permite comprobar si hay un elemento en la cola.

Espero que os haya gustado esta introducción a CCR, es los dos próximos post explicare como esto es usado desde DSS que es el corazón de Robotics Studio.

Luis.

Robotics Studio

Recientemente he tenido que impartir un curso sobre Robotics Studio en el Innovation Center de Mondragón, centro de innovación dedicado a tecnologías embebidas. Robotics Studio MSRS, es un herramienta estupenda para que profesionales y entusiastas empiecen a programar aplicaciones robóticas.

Sin entrar a valorar mucho lo que es una aplicación robótica, diré que, básicamente es lo mismo que cualquier software que construimos en nuestro pc. Entrada de datos, que se procesan de alguna manera y se devuelve de otra manera. Como siempre se nos ha dicho el desarrollo de software es como una caja negra que procesa datos. Pues en las aplicaciones robóticas, ocurre lo mismo, salvo que los datos vienen de los diferentes sensores que el robot incorpora. Así que básicamente nos dedicamos a trabajar con esos datos provenientes del robot y a hacer algo con ellos.

Si bien es cierto que el desarrollo de software ha cambiado mucho desde sus inicios, podemos decir que Robotics Studio, representa esa evolución que el desarrollo de software tuvo con respecto al desarrollo de aplicaciones. Decir que Robotics Studio está pensado para orquestar todos esos datos provenientes del robot desde el PC, aunque también se puede “orquestar” desde un móvil. MSRS está diseñado con .NET así que podemos usar cualquiera de nuestro lenguaje favorito de .NET para programar aplicaciones robóticas.

Robotics Studio está compuesto básicamente de dos componentes principales, CCR (Concurrency and Coordinator runtime) y DSS (Descentrailized Software Services)

Como se empieza con el SDK?

CCR

Pues bien, hay que tener varios conceptos claros a la hora de programar aplicaciones para Robotics Studio, como se ha dicho antes una aplicación robótica recibe los datos del robot y los procesa. Ante esta sencilla frase se encuentra el porqué del modelo de desarrollo de MSRS. Un problema que nos podemos encontrar a la hora de programar estas aplicaciones es que los datos de los sensores pueden venir en cualquier momento, y todos a la vez con lo que tenemos que ser capaces de poder lidiar con esta concurrencia desde el primer momento. Pero eso no es lo único porque además de que los sensores nos pueden dar muchos valores a la vez, podemos trabajar con UI y sincronizar todos esos datos con un formulario de Windows Forms, así que, aunque la cosa parece sencilla, en breve se complica.

Para solucionar este problema de base, la concurrencia, MSRS tiene una librería que nos va a permitir programar estás aplicaciones robóticas sin tener que preocuparnos, mucho, de la concurrencia. Si lo pensamos por un momento, tenemos una cola de datos en la que el robot va insertando los datos provenientes de su sensor, y una aplicación que va sacando esos datos de la cola. Esta cola, por supuesto, ha de ser segura frente a subprocesos y concurrente. Para ello disponemos, en MSRS, de una clase muy especial, Port<T>, que nos permite crear ese puerto de comunicación entre un dispositivo y la aplicación. Esta clase Port<T> que es genérica, permite que podamos definir el tipo de datos proveniente de nuestro sensor de manera personalizada.

Una vez que ya tenemos el puerto definido en cuanto al tipo de dato que va a procesar tenemos que ser capaces de procesar de alguna manera y de forma individual los valores que se van introduciendo en el puerto. Como he dicho anteriormente, MSRS tiene en mente constantemente el desarrollo de aplicaciones concurrentes, así que para poder procesar esas tareas tenemos que tener nuestro propio ThreadPool.

Dentro de MSRS, tenemos dos clases especiales, Dispatcher y DispatcherQueue, que nos permite crear un dispatcher para generar Threads trabajadores que proceses las tareas provenientes de los Port<T> y DispatcherQueue que nos va a permitir que podamos encolar las tareas de procesamiento de los puertos, pudiendo así procesar desde varios puertos en la misma cola. Cada tarea individual se procesa en un Thread diferente para que así la aplicación sea concurrente. Estas dos clases son las clases que MSRS nos provee para que nosotros podamos escribir el procesamiento de las tareas. Podemos configurar el número de Threads que queremos por Dispatcher y puede haber más de un Dispatcher por proceso y dominio de aplicación.

Pues bien una vez que tenemos definido como se van a procesar las tareas, tenemos que sacar los elementos de los Port<T> y especificar el delegado que será el que se encargue de procesar los elementos de ese puerto. Para esta tarea tenemos los Arbiters, que es una clase estática que permite crear un proceso automático para extraer los valores del Port<T> y procesarlos. Aquí tenemos un ejemplo completo.

public void SimplePort()
{
    Port<string> puerto = new Port<string>();

    Dispatcher d = new Dispatcher(0,
        ThreadPriority.Normal,
        DispatcherOptions.UseBackgroundThreads,
        ApartmentState.STA, "ejemplo");

    DispatcherQueue q = new DispatcherQueue("cola", d);

    Arbiter.Activate(q,
        Arbiter.Receive<string>(true, puerto, 
        delegate(string item)
            {
                Console.WriteLine(item);
            }
    ));

    for (int x = 0; x < 1000; x++)
    {
        puerto.Post(DateTime.Now.ToString());
    }
}

Si nos fijamos con la clase Arbiter, activamos el procesamiento en el DispatcherQueue (q), los elementos que se van recibiendo del Port<T> puerto. Además de especificar con un delegado anónimo el método que procesará los mensajes recibidos en el Port<T>.

Este es el modo sencillo y automático de procesar las tareas restantes del puerto, sin nos fijamos un poco más abajo podemos encontrar como se postean los mensajes en el Port<T> y esos mensajes se van procesando de manera asíncrona.

Podemos tener varios DispatcherQueue en un Dispatcher, y el motivo es que podemos querer diferentes tipos de retención de mensajes en nuestra cola. Imaginemos por un momento que estamos procesando imágenes procedentes de la cámara del robot, pero por algún motivo tenemos 50 imágenes restantes por procesar, por motivos de rendimiento solo nos puede interesar procesar las últimas 25 imágenes recibidas y que las que se quedaron atrás en el tiempo simplemente que se descarten.

Al final la clase Arbiter a lo que se dedica es a procesar Tareas en los Dispatcher, tareas que están definidas en la interfaz ITask. Está interfaz que nosotros podemos implementar de alguna manera para poder definir nuestras propias tareas, es la clase Arbiter la que se encarga de exponer esa funcionalidad de Tareas de una manera más comida para el programador sin tener que estár constantemente implementando la interfaz.

De hecho podemos utilizar los Dispatcher sin necesidad de Port<T> simplemente como un procesador de tareas. En este ejemplo de código lo podemos ver.

void RunFromHandler()
{
    Dispatcher d = new Dispatcher(2, "Test Pool");

    DispatcherQueue q = new DispatcherQueue("Test Queue", d);
    
    ITask[] t = new ITask[100000];
    for (int x = 0; x < t.Length; x++)
    {
        t[x] = Arbiter.FromHandler(SimpleHandler);
    }
    Arbiter.Activate(q, t);
}


void SimpleHandler()
{
    
    Console.WriteLine("Start Simple Handler Thread {0}", Thread.CurrentThread.ManagedThreadId);
    for (int i = 0; i < 10; i++)
    {
        Wait(10);
        Console.Write(i + " ");
    }

    Console.WriteLine("Finished Simple Handler Thread {0}", Thread.CurrentThread.ManagedThreadId);
}

Esto es una breve introducción del CCR que seguiré expandiendo en otros artículos, mostrado como se pueden hacer composiciones de tareas más complejas y como este CCR se puede usar en aplicaciones que no sean robóticas ni dentro del MSRS en donde la concurrencia es un problema desde el inicio del proyecto.

[Evento] Depuración y Optimización Avanzada de Aplicaciones (recursos)

Hola a todos!!. Primero dar gracias a todos por haber venido a verme a la charla, y gracias también por los mails de agradecimiento!!.

La presentación de power point de la charla.

evento-depuracion

El sitio web de ejemplo aquí.

TinyGet (Herramienta para hacer las peticiones a la web) está disponible como IIS 6 Resource ToolKit http://support.microsoft.com/kb/840671

Libros:

CLR Via C#

clip_image001

Este libro es uno de los mejores. Explica el funcionamiento del CLR (Common Language Runtime) expuesto desde C#.

http://www.amazon.com/CLR-via-Second-Pro-Developer/dp/0735621632%3FSubscriptionId%3D15HRV3AZSMPK0GXTY102%26tag%3Die8suggestion-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0735621632

Professional .NET Framework 2.0

clip_image002

http://www.amazon.com/Professional-NET-Framework-2-0-Programmer/dp/0764571354%3FSubscriptionId%3D15HRV3AZSMPK0GXTY102%26tag%3Die8suggestion-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0764571354

 

Windows Internals

Windows® Internals: Including Windows Server 2008 and Windows Vista, Fifth Edition (PRO-Developer)

Windows Internals es el mejor libro de referencia de Windows, esta 5º edición incluye Windows Vista y Server 2008. Es un libro fundamental para conocer la plataforma Windows.

http://www.amazon.com/Windows%C2%AE-Internals-Including-Windows-PRO-Developer/dp/0735625301%3FSubscriptionId%3D15HRV3AZSMPK0GXTY102%26tag%3Die8suggestion-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0735625301

Blogs:

http://blogs.technet.com/markrussinovich/ (Mark Russinovich) Creador de la suite sysinternals

http://www.wintellect.com/cs/blogs/jrobbins/

http://blogs.msdn.com/tess/

Herramientas:

En este blog en post anteriores podeís encontrar varios post de como se configura el entorno de depuración con símbolos y demás. Además de eso varias herramientas útiles.

Process explorer, sin duda la herramienta definitiva para extraer información de que está haciendo Windows. Nos muestra información sobre rendimiento, consumo de memoria, threads, manejadores y demás.

Process Monitor, igual que process explorer solo que es un registro de la actividad de Windows, en tres categorías Threads, Registro y IO

Notas:

Muchos de vosotros me habeís enviado mails preguntándome varias cosas respondo a todo el mundo desde aquí porque son preguntas interesantes.

Q: Yo vivia muy feliz antes de este evento, ahora siento miedo ¿Porqué?

A: Bueno, las razones son varias, pero creo que al exponer lo complicado que puede ser el desarrollo de aplicaciones uno siente miedo ante esto. Teniendo en cuenta que durante el evento se ha hablado de .net que es un lenguaje de alto nivel, en el que hay muchas cosas que ayudan a programar y hacer las cosas más fáciles, resulta más chocante aún. El caso es que la informática es una de las disciplinas más complicadas que existen por ahí afuera. Y si no me creeis leeros este ensayo de Edsget W. Dijkstra desde aquí.

Q: Todos los ejemplos han sido de una aplicación ASP.NET atacando directamente al proceso w3wp.exe, ¿Es posible hacer esto con otro tipo de aplicaciones?

A: Desde luego las demos estaban preparadas así pero se pueden generar dumps de aplicaciones de escritorio ya sea Windows Forms, WPF o lo que sea. De hecho este tipo de depuración es especial porque está pensada para cuando no se está delante de la maquina que tiene el problema.

[Evento] Depuración y Optimización Avanzada de Aplicaciones

Hola a todos, el próximo jueves 2 de octubre participo en la charla “Depuración y Optimización Avanzada de Aplicaciones” que se celebrará en el CIIN (Centro de innovación de Microsoft de Cantabria) por parte de Plain Concepts, y con mi compañero Pablo Doval.

Por cierto el evento se retransmitirá online a través de la web de Microsoft (el enlace a final del post).

evento-depuracion

Cuando desarrollamos Software, pasamos por una serie de etapas, desde el diseño hasta el despliegue final, en las que buscamos proporcionar soluciones que resuelvan de forma excelente los problemas y requerimientos planteados. Sin embargo, el camino no es fácil y muchas veces nos olvidamos de aspectos muy importantes como son la depuración, la optimización y el testeo de nuestras aplicaciones como camino a lograr aplicaciones con el mayor nivel de calidad posible. Para cubrir esta etapa imprescindible en todo desarrollo de software, os presentamos en colaboración con Plain Concepts una nueva jornada de la que se puede hablar durante días y días: Depuración y Optimización Avanzada de Aplicaciones.

La jornada que os proponemos será gratuita por cortesía de Plain Concepts y constará de un repaso de la depuración básica con Visual Studio, profiling de problemas de rendimiento y depuración avanzada con WinDbg. Se tocarán temas como análisis de rendimiento y pruebas de carga, localización de puntos calientes y cuellos de botella, resolución de problemas esquivos (cuelgues, pérdidas, bloqueos, CTDs…) tanto en vivo como de modo postmortem mediante el análisis de volcados de memoria y otras técnicas de depuración. También se abordarán, durante el transcurso de la sesión, aspectos de soportabilidad como la construcción de un servidor de símbolos sincronizados, la generación de volcados de memoria en nuestras aplicaciones, etc. Como viene siendo habitual, la parte teórica irá acompañada de demostraciones prácticas sobre escenarios habituales de optimización y resolución de problemas.

La jornada será impartida por Pablo Alvarez Doval. Pablo ha estado vinculado a las tecnologías Microsoft desde el inicio de su carrera profesional, y fue miembro del GTSC de Microsoft en el equipo de SQL Server. Actualmente trabaja para Plain Concepts, donde lidera la iniciativa DOT (Debugging & Optimization Team), destinada a ayudar a sus clientes en la resolución de problemas de rendimiento o problemas de difícil trazabilidad. Dispone de un blog en http://geeks.ms/blogs/palvarez, donde aborda principalmente temas de rendimiento, WinDbg y SQL Server.

http://www.ciin.es/web/servicios/eventos/Paginas/DepOptApp021008.aspx?Fecha=02-10-2008 

http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032390753&EventCategory=4&culture=es-ES&CountryCode=ES 

http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032390757&EventCategory=4&culture=es-ES&CountryCode=ES

ResourceDictionary y el soporte para Blend en WPF

La clase ResourceDictionary permite tener un diccionario de recursos para que lo utilicemos en nuestras aplicaciones. Dentro de WPF es normal usar esta clase, ya que como explicamos en otro post anterior (WPF para programadores de Windows Forms 5), estos se pueden sumar o “Merge” con otros diccionarios para tenernos todos centralizados dentro de Application.Current.Resources.

Esta característica para el soporte te temas (Themes) y para tener en un lugar centralizado los recursos de la aplicación es estupendo, pero si alguna vez has hecho un control con soporte para tiempo de diseño, digamos Visual Studio 2008 o Blend, hacer que esto funcione se puede convertir en un infierno. Veamos porque.

Esta clase Application es una clase implementada como un singleton que gestiona el ciclo de vida de una aplicación WPF, únicamente puede haber una instancia por dominio de aplicación. Imaginemos que por un momento tenemos un código parecido a este.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;

namespace ApplicationDesingTime
{
    public class MyCustomControl : ContentControl
    {
        public MyCustomControl()
        {
            Template = (ControlTemplate)App.Current.Resources["Style1"];
        }
    }
}

En el que estamos haciendo un control personalizado que cambia su Template actual para cambiar el árbol visual de controles y tener otro aspecto. Hasta aquí todo bien estamos accediendo al diccionario de recursos que tenemos dentro de nuestra aplicación. Si compilamos y nos llevamos este control que debería de tener este aspecto a blend y lo usamos aparece esto otro.

image

Blend

Esto porque ocurre, si ejecutamos la aplicación funciona perfectamente pero si la visualizamos en Blend resulta que no se visualiza correctamente. Es una lástima que tengamos nuestro control, más o menos complejo, pero no podamos verlo en tiempo de diseño. La clave está en la clase Application. Como antes he comentado la clase Application es única por dominio de aplicación lo que significa que dentro de Blend o Visual Studio existe una clase Application, pero es que resulta que, en el caso de Blend, la clase Application corresponde a la propia aplicación de Blend!!. Esto es un bug o algo así del framework o de Blend, o es que simplemente Blend es un entorno de hosting para nuestros controles y aunque Blend crea instancias de nuestros controles para tiempo de diseño, no es el mismo entorno que cuando se ejecutan.

Y ahora, ¿ya no vamos a tener controles con tiempo de diseño como los que viene con WPF?, claro que sí, pero hay que hacerlo de una manera especial.

Lo primero de todo es que necesitamos alguna manera de saber cuando estamos en blend o cuando estamos ejecutando la aplicación. Esto lo podríamos hacer viendo si el nombre del proceso en el que está mi control es blend.exe, pero si estamos en Visual Studio o en otro programa esto no funcionará, además, WPF tiene una manera más elegante de sabes si estamos en tiempo de diseño o no.

En System.ComponentModel hay una clase System.ComponentModel.DesignerProperties que tiene un método estatico, llamado GetIsInDesignMode que acepta un DependencyObject y te devuelve un booleano que indica si el control está en tiempo de diseño o no. Esto se hace a través de una DependencyProperty atachada que hay en esa clase.

Esta característica también está en Windows Forms, pero a diferencia de Windows Forms, si se consulta esta propiedad en el constructor, esta propiedad está establecida, mientras que en Windows Forms después de crear el objeto el diseñador establece la propiedad de tiempo de diseño.

Ahora que ya sabemos esta información vamos a hacer una clase helper que nos permita acceder a los elementos del ResourceDiccionary desde todos los tiempos.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;

namespace ApplicationDesingTime
{
    public class MyCustomControl : ContentControl
    {
        public MyCustomControl()
        {
            //Template = (ControlTemplate)App.Current.Resources["Ejemplo"];
            Template = TemplateHelper.GetData<ControlTemplate>(this, "Ejemplo");
        }
    }
}

image

Para iniciar un ResourceDictionary hay que establecer la propiedad Source indicando cual es el fichero .xaml que se va a utilizar como origen de datos. Esta propiedad Source es de tipo Uri, en el que hay que establecer el formato de ensamblado y ruta en un formato especial.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows;
using System.Diagnostics;

namespace ApplicationDesingTime
{
    public static class TemplateHelper
    {
        private static ResourceDictionary DesingTimeAppDiccionary;

        public static T GetData<T>(DependencyObject context, string name)
        {
            if (DesignerProperties.GetIsInDesignMode(context))
            {
                if (DesingTimeAppDiccionary == null)
                {
                    DesingTimeAppDiccionary = new ResourceDictionary();
                    try
                    {
                        DesingTimeAppDiccionary.Source = new Uri("/ApplicationDesingTime;component/Dictionary1.xaml", UriKind.RelativeOrAbsolute);
                    }
                    catch (Exception ex)
                    {
                        Trace.WriteLine(ex.ToString());
                    }
                }
                return (T)(object)DesingTimeAppDiccionary[name];
            }
            else
            {
                return (T)(object)App.Current.Resources[name];
            }
        }
    }
}

El formato de la Uri sería algo así.

/{assembly};component/{fichero.xaml}

Espero que esto os sirva en los proyectos de WPF que hagais y si haceis muchos controles con tiempo de diseño es interesante este pequeño truco.

Y por cierto si estais pensando en hacer una clase con xaml y un fichero de codigo trasero, hay que tener en cuenta que después esa clase no puede ser la clase base de otro control que esté compuesto de xaml y un fichero .cs así que esta es la mejor manera de modificar el arbol visual de un control para personalizarlo. Pero de eso hablaremos en otro post.

[Curso] WPF para programadores de Windows Forms 6

En la última entrega del curso de WPF para programadores de Windows Forms, hablamos de los DataTemplate, que permitían modificar el aspecto visual de un control. Ahora en este articulo vamos a hablar un poco más sobre esta característica y como se puede extender.

Imaginemos por un momento que empezamos a usar esta característica que junto con los estilos permiten modificar el aspecto de un control de una manera muy sencilla, pero que ahora queremos que el usuario, por ejemplo, elija un tema de una lista de temas disponibles. ¿Cómo podríamos encajar esta funcionalidad con los DataTemplate tendríamos que tener algún mecanismo para poder decidir en tiempo de ejecución que DataTemplate tenemos que elegir. Pero la pregunta es cuando hacemos esto ¿cuando el control se ha cargado?, ¿en el constructor?, la respuesta es DataTemplateSelector .

Esta clase, DataTemplateSelector provee una manera de elegir un DataTemplate en tiempo de ejecución, cuando el control se va a enlazar y se va a construir el árbol visual de controles de nuestro elemento.

DataTemplateSelector tiene un método virtual,

public virtual DataTemplate SelectTemplate(Object item, DependencyObject container)

En el que se nos pasa la referencia del objeto de datos el cual el control está enlazado y el control en sí que es pasado en el container. De esta manera y a través de un enlace a datos podemos decidir que DataTemplate tenemos que establecer. Una vez que tenemos una clase que hereda de DataTemplateSelector, y hemos sobreescrito el método SelectTemplate, tenemos que crear una instancia de esta clase y establecerlo en la propiedad ContentTemplateSelector de la clase ContentControl.

Sería algo parecido a esto:

using System.Windows;
using System.Windows.Controls;

namespace SDKSample
{
    public class TaskListDataTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate

                SelectTemplate(object item, DependencyObject container)
        {
            if (item != null && item is Task)
            {
                Task taskitem = item as Task;
                Window window = Application.Current.MainWindow;
                if (taskitem.Priority == 1)
                    return
                    window.FindResource("importantTaskTemplate") as DataTemplate;
                else
                    return
                    window.FindResource("myTaskTemplate") as DataTemplate;
            }
            return null;
        }
    }
}

Otra necesidad que se nos puede surgir es de generar DataTemplates a partir de código, esto que a priori no es recomendable puesto que añade complejidad extra al código y no permite modificar el aspecto del control a través del xaml y puede que en algún momento sea necesario además de que es necesario recompilar la aplicación.

Si echamos un vistazo a la clase DataTemplate vemos que tiene una propiedad VisualTree, que es el nodo raíz del DataTemplate, el control raíz del DataTemplate. Pero si nos paramos a ver por un momento el tipo de esta propiedad vemos que es de tipo FrameworkElementFactory y no DependencyObjecto Control como podríamos esperar. Esta clase FrameworkElementFactory es en realidad una factoría de FrameworkElement, y es usada por el constructor de controles para inicializar un control. Si nos fijamos en el construcor de esta clase el parámetro que se nos pide es un System.Type que después usara para crear un objeto de ese tipo con System.Activator.

Si miramos los métodos de que dispone esta clase tenemos:

· AddHandler, que nos permite añadir un manejador a un RouteEvent.

· AppendChild, que permite añadir un hijo al elemento actual.

· RemoveHandler, que permite eliminar un manejador previamente creado.

· SetBinding, que permite añadir un binding.

· SetValue, esta es si cabe es el método más interesante de todos ya que nos permite establecer valores de los DP de nuestro control.

En una inicialización normal de un control de WPF podríamos hacer algo así:

Grid grid = new Grid();

Grid.Margin = new Thinkness(3);

Realmente la propiedad Margien es un wrapper en una propiedad del CLR de un DependencyProperty llamado MarginProperty.

Esta sería la manera de hacerla con WPF:

Grid grid = new Grid();

Grid.SetValue(Grid.MarginProperty,new Thinkness(3));

Así que la clase FrameworkElementFactory guarda una lista de los DP que se han establecido para después establecerlos en el control que instancia internamente.

Google Chrome

No suelo escribir sobre las novedades que la web nos ofrece a menos que sea algo interesante para el programador, pero viendo esto de google chrome no he podido evitarlo. Creo que todo el mundo se ha bajado el navegador en cuestión si no lo ha hecho lo invito.

La primera impresión buena, es un diseño sencillo. Empiezo a navegar y me llevo una sorpresa. Normalmente siempre tengo abierto el process explorer un sustituto del administrador de tareas de windows, y cuando he mirado al árbol de procesos me he llevado una sorpresa muy grande.

 

image

Resulta que el navegador de chrome abre un proceso por cada pestaña, parece que eso de aislar cada tab por si uno falla que falle solo esa pestaña lo han llevado al extremo.

Pero resulta que esto es una muy mala práctica. Como sabréis una de la cosa más costosa para Windows es iniciar un proceso, ya que debido a las características de seguridad y aislamiento Windows genera una memoria virtual para cada proceso además de todas las estructuras necesarias para que el proceso se pueda iniciar. Pues me parece que esta solución de los “ingenieros” de software de google, es la más obvia, cutre y sobre todo la más fácil. Ni que decir tiene que este modelo de navegador hace que se generen muchos procesos, que, por muy ligeros que sean, tienen que cargar sus dll, reservar memoria a Windows y demás tareas. Es como si en la programación de páginas web cambiásemos el modelo de hosting de asp.net a un modelo cgi en que cada vez que se hace una petición se inicia el w3_wp.exe. Eso por ejemplo lo vemos una barbaridad, pues la gente de google es lo que ha hecho.

No sé si sabéis que en .net existe el mismo problema para los entornos de hosting, un proceso, asp.net o Sql Server. Imaginaros por un momento que tengo mi web en asp.net en un hosting compartido, y una de las web que se aloja en ese servidor, que también está dentro del mismo proceso w3_wp.exe hace una operación no valida y genera una excepción crítica, resulta que el proceso se cerraría y se reiniciaría y yo que también estoy hay sufriría la incompetencia de mi vecino de memoria. Esto desde luego es una cosa muy fuerte, por eso en .NET existe el concepto de Dominio de Aplicación, System.AppDomain, que básicamente es un aislamiento lógico para las aplicaciones, incluso si están dentro del mismo dominio. Esto no es gratuito puesto que a poco que conozcas un poco la plataforma Windows, sabrás que Windows comparte las dll cargas en el mismo proceso, lo que hace que se mejore el consumo de memoria.

Que por cierto si dentro del mismo tab cambias la web el proceso que has usado para renderizar la anterior se cierra y se abre uno nuevo, toda una aberración, ni siquiera reutilizan el proceso, como yo decía un modelo cgi de renderizado de webs. También para los plugins utiliza el mismo proceso, podemos verlo con las líneas de comando.

 

image

Así que lo único que digo sobre el navegador de google, que me importa muy poco, por no decir nada que soporte acid test o lo que sea o los estándares, es que el modelo de aislamiento de tab me parece una castaña muy gorda y que en vez de agitar internet con un lanzamiento de estas características para presentar esta cosa, por favor cállate y presenta algo innovador de verdad.

Actualización: Parece que Microsoft en la beta del IE8 con el UAC activado hace lo mismo, y tengo que decir que me parece una castaña muy gorda, parchear el navegado y no inventar nada nuevo. Yo no tengo el UAC activado.

 

ie8beta22

Windows Vista con UAC gentileza de mi colega Pedro Laguna

 

ie8

Y este es mi escritorio sin UAC con IE8 Beta2 con varios tabs y el process explorer abierto.

Disponible .NET Framework 3.5 SP1 Sources

A través del blog del Reference Source Code Center Team Blog, http://blogs.msdn.com/rscc/archive/2008/08/28/net-framework-3-5-sp1-sources-are-available.aspx, disponible el código fuente del .NET Framework 3.5 SP1. Si trabajáis con el código fuente del framework mientras depuráis las aplicaciones, esta release es justo lo que estabais buscando. Además en el SP1 de Visual Studio 2008 trae directamente el soporte para el código fuente del framework.

Resuelto – Usar un origen http en un BitmapImage ralentiza tu aplicación WPF

Como sabréis hace poco escribí un post sobre un problema que encontré dentro de WPF relacionado con el rendimiento de una aplicación que estaba desarrollando. El caso es que además de escribir un post inicie también un comentario dentro de la web de connect de Microsoft en https://connect.microsoft.com/VisualStudio/ para que Microsoft supiera que está pasando, pues bien hoy me han respondido al comentario y resulta que efectivamente es un bug y que lo van a solucionar.

Aquí tenéis el enlace del post original

http://www.luisguerrero.net/post/2008/05/Usar-un-origen-http-en-un-BitmapImage-ralentiza-tu-aplicacioacute3bn-WPF.aspx

y en enlace de connect

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=344785 (requiere inicio de sesión)

Lo interesante de este bug que como una herramienta como WINDBG y SOS nos puede ayudar a solucionar un problema en nuestro software.

Saludos a todos.

[Curso] WPF para programadores de Windows Forms 5

[Básico – Medio]

Hola de nuevo, hoy vamos a hablar de una característica muy interesante de WPF, los DataTemplate o Data Templating.

¿Qué es un DataTemplate?

Es, como su nombre incica, una plantilla de datos. Pero, ¿a que se refiere con datos?, pues con datos se refiere a cualquier elemento dentro del árbol de controles de WFP. Eso incluye controles, controles de usuario y en general cualquier instancia de una clase. Eso significa que podemos añadir a un ListBox un elemento nuevo y que este sea una clase de negocio que represente un pedido.

Esta característica está muy bien, ya que no necesitamos utilizar ningún tipo de patrón a la hora de añadir a la presentación de nuestras aplicaciones nuestros objetos de negocio. Simplemente añadiéndolo. Pero el caso es que, cuando alguien añada una clase de objeto de negocio a una lista de elementos de un ListBox, el ListBox no sabe como “pintar” o representar ese elemento dentro de la UI, así que lo único que hace es llamar al método ToString() de nuestra clase de negocio.

Podemos por supuesto sobrescribir el método ToString() de nuestra clase de negocio pero el caso es que solamente seremos capaces de representar texto en la interfaz de usuario, y teniendo en cuenta las capacidades de WPF eso es algo que no se puede permitir. Tenemos que tener alguna manera de especificar cómo queremos que se dibuje ese Tipo de dato en pantalla.

Aquí es donde entran los DataTemplate, esta clase es una árbol de controles que van a representar nuestro objeto de negocio.

Imaginemos por un momento que tenemos una clase Cliente tal que así:

public class ClienteV1
  {
      public string Nombre { get; set; }
      public int CodigoCliente { get; set; }
      public DateTime Fecha { get; set; }
  }

Tenemos una serie de propiedades que definen el estado de nuestro cliente, pues bien lo que vamos a hacer es definir un árbol de controles en XAML para representar la clase cliente.

<DataTemplate>
    <WrapPanel>
        <Label/>
        <TextBox/>
        <TextBlock/>
    </WrapPanel>
</DataTemplate>

Ahora mismo únicamente tenemos un XAML que define un árbol de controles que podríamos utilizar para representar nuestra clase cliente, lo único que nos falta es “mapear” o enlazar a datos (DataBinding) las propiedades del objeto de negocio cliente con los controles de nuestro árbol. Se hace así:

<DataTemplate>
    <WrapPanel>
        <Label Content="{Binding Path=Nombre}" />
        <TextBox Text="{Binding Path=Fecha}" />
        <TextBlock Text="{Binding Path=CodigoCliente}" />
    </WrapPanel>
</DataTemplate>

Si nos fijamos por ejemplo en la etiqueta Label, en el atributo “Content” tenemos esto:

Content=”{Binding Path=Nombre}”

¿Qué estamos especificando ahí?, pues básicamente lo que le queremos decir a WPF es que si en el objeto de destino (nuestra clase Cliente) encuentra por reflexión una propiedad, y repito solo funciona con propiedades, con ese nombre pues que obtenga su valor y que lo establezca en la Dependency Property Content del control Label.

Pues ya esta!!.

Ya tenemos definido nuestro DataTemplate para el objeto de negocio Cliente. Es más aunque tenemos sobrescrito el método ToString() en nuestra clase Cliente WPF no hace caso y simplemente establece el DataTemplate.

Características avanzadas de los DataTemplate.

Nosotros en el ejemplo que hemos realizado hemos establecido el valor de este DataTemplate para el control en que estamos, en nuestro caso un ListBox. Puede ser muy común que este DataTemplate se tenga que usar en más sitios dentro de WPF, y lo suyo sería tenerlo como un recurso compartido para que sea accesible desde cualquier sitio. Esto se puede hacer así:

<ListBox HorizontalAlignment="Right" Margin="0,70,57,45" Width="85" IsSynchronizedWithCurrentItem="True" ItemTemplate="{DynamicResource DataTemplate1}"/>

Ahora bien tenemos que definir ese DynamicResource con valor DataTemplate1. Esto se hace a través de unos ficheros llamados ResourcesDiccionary que son una especie de ficheros xaml que solamente contiene recursos compartidos por la aplicación, podemos ver uno aquí:

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <DataTemplate x:Key="DataTemplate1">
        <Grid/>
    </DataTemplate>
    <!-- Resource dictionary entries should be defined here. -->
</ResourceDictionary>

Aunque se haya creado este fichero se tiene que especificar de alguna manera como se tiene que hacer referencia en todo el proyecto, para eso existen los recursos a nivel de aplicación, que los tenemos disponibles en el fichero app.xaml.

Pero lo que tenemos en este fichero son los recursos en sí, no referencias a ficheros externos. Así que tenemos que combinar todos los diccionarios en uno para que sean usados de manera global.

<ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="ResourceDictionary.xaml"/>
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

Y así es como se combinan los diccionarios para que estén disponibles en toda la aplicación.

El codigo de la aplicación esta aquí [CursoWPF5.zip]

En el siguiente post del curso hablaremos un poco más en detalle de los DataTemplates, como subscribirse a eventos dentro de los controles que están en la DataTemplate y además como hacer DataTemplates a partir de código.