How to: Remove diacritics (accents) in C# strings

cs

Quick note: How to remove diacritics (accents) from a C# string?
Use this extension method ;)

public static string RemoveDiacritics(this string input)
{
    var stFormD = input.Normalize(NormalizationForm.FormD);
    var len = stFormD.Length;
    var sb = new StringBuilder();
    for (int i = 0; i < len; i++)
    {
        var uc = System.Globalization.CharUnicodeInfo.GetUnicodeCategory(stFormD[i]);
        if (uc != System.Globalization.UnicodeCategory.NonSpacingMark)
        {
            sb.Append(stFormD[i]);
        }
    }
    return (sb.ToString().Normalize(NormalizationForm.FormC));
}

How to: Server Side Filter database (Entity Framework + DevExpress Filter control)

Imagine you have a table with millions of rows. It’s not a good idea showing all these data in a grid or similar, and it doesn’t matter you’re developing a web or desktop application… It’s not a good idea at all.

In these cases we should use conditional filters applied in the data source (usually a database) to get part of the information and return only the rows that match with the specified criteria. Using this technique the amount of network traffic could be reduced to a hundreds of rows or less, depending on the criteria.

There are different ways of accomplish that, but today I’d like to focus on apply this technique using a control from the DevExpress suite: The Filter Editor control.

DXFilterControl

 

As you can see the control looks nice, and it’s quite simple to use: You just need to link this control to another (usually a Grid or Tree), and automatically will retrieve the columns and values information from the source control. Then you’ll be able to filter the linked control and get a filter string which you can reuse later in other controls of the suite.

However the previous filter has the disadvantage that is a client filter, and is applied after we retrieve all the rows from the data source, not before. Our goal have to be apply the filter before getting the information.

Today I’ve been playing a little bit with this control, using a SQL Server database that contains a products table with 3.7 million rows and Entity Framework 6.0 as an ORM.

Note: For this test I’d like to use a SQL Tabled-Valued Function to access the data instead of using the default DbSet, because it’s supposed that I’ve to do some hard calculations inside the function. But you can also use the EF DbSet directly, as usual.

EFModel

Now our goal here is:

  1. Create at runtime a filter over the Products table using the filter control.
  2. Parse that filter string and adapt it to the EF syntax.
  3. Append the filter to the mapped function (thx to IQueryable!) before execution.
  4. Finally, execute the filtered query against the data source

First we need to add an EF designer (we won’t use Code First because we’re going to map a Tabled valued function with is not supported). And add the table Products and the GetAllProducts function.

In our form, we just need to add a couple of Devexpress controls: A GridControl and a FilterControl, linked using the FilterControl SourceControl property (this allows the filter control to retrieve the names and data types of the grid columns).

DynamicFiltersEF

Then we’ll add three buttons. The first one will retrieve the first 25.000 rows from the database (previously I’ve tried to get all rows from table, but the app crashed with an OutOfMemory exception ;))

The second button (this is the interesting one) will execute the current filter from the FilterControl.

Let’s code:

The first button is really simple. It’s just a query over the GetAllProducts function adding a where clause which will be resolved later (because EF is based on IQueryable<T>) when calling ToListAsync method.

private async void simpleButton1_Click(object sender, EventArgs e)
{
    using (var context = new TestBigDbEntities())
    {
        var filteredproducts = context.GetAllProducts().Where(p => p.ProductId <= 25000);
        await ExecuteQueryAsync(filteredproducts);
    }
}

private async Task ExecuteQueryAsync(IQueryable filteredProducts)
{
    clock.Restart();
    productBindingSource.DataSource = await filteredProducts.ToListAsync();
    clock.Stop();
    Text = clock.ElapsedMilliseconds.ToString("n2");
}

For the second button we need something more. Something that allows us to translate the filter into a valid where clause, and append it to the function.  The good news are that this functionality is provided natively by Devexpress:

private async void simpleButton2_Click(object sender, EventArgs e)
{
    var converter = new DevExpress.Data.Linq.CriteriaToEFExpressionConverter();
    using (var context = new TestBigDbEntities())
    {
        var filteredproducts =
                DevExpress.Data.Linq.Helpers.CriteriaToQueryableExtender.AppendWhere(
                context.GetAllProducts(),
                converter,
                filterControl1.FilterCriteria);
        await ExecuteQueryAsync(filteredproducts);
    }
}

All we’ve to do is that:

Clean and simple. The first one creates a converter for translating the filter into EF syntax, while the second one appends the filter to the EF function using the previous converter.
And finally, here’s the SQL in the profiler. Exactly what I’ve expected.

SQLProfiler

So well… if you’re using Devexpress in your current project there’re no excuses for not including dynamic filters that user can save and reuse at runtime, uh? :P

Happy coding!

Bonus

The third button code shows how to get the TSQL syntax from the Filter control, that you can use it to query the database directly ;)

private void simpleButton3_Click(object sender, EventArgs e)
{
    var tsql = DevExpress.Data.Filtering.CriteriaToWhereClauseHelper.
        GetMsSqlWhere(filterControl1.FilterCriteria);
    MessageBox.Show(tsql);
}

BonusTSQLFilter

Extract extra large Icon from a file, including network paths!

Edit (04/16/2014): Added a new function called GetBitmapFromFolderPath, which returns the associated icon from the path to a Folder (or drive!).

image

Sometimes we are required to show a list of files with their associated icons. This task sounds quite easy, and in fact it is… Except if you have to deal with files in network paths or you want to get different icons sizes, apart the typical 32×32.

If you want to achieve this using managed code (the easy way), there is a static method called ExtractAssociatedIcon under the class Icon to achieve that, but sadly this method doesn’t work with UNC paths neither return other sizes that 32×32 pixels.

In my current project I needed to show four different icons sizes (including the extra-large icon, also called “jumbo”), so I’ve decided to use some functions and structures from the Win32 API. Of course, if anyone knows a better way to do it, please contact with me ASAP :)

First, let’s see the final code:


private static IntPtr GetIconHandleFromFilePath(
    string filepath, IconSizeEnum iconsize)
{
    var shinfo = new Shell.SHFILEINFO();
    const uint SHGFI_SYSICONINDEX = 0x4000;
    const int FILE_ATTRIBUTE_NORMAL = 0x80;
    const int ILD_TRANSPARENT = 1;
    uint flags = SHGFI_SYSICONINDEX;
    var retval = SHGetFileInfo(filepath, FILE_ATTRIBUTE_NORMAL,
        ref shinfo, Marshal.SizeOf(shinfo), flags);
    if (retval == 0) throw (new System.IO.FileNotFoundException());
    var iconIndex = shinfo.iIcon;
    var iImageListGuid = newGuid("46EB5926-582E-4017-9FDF-E8998DAA0950");
    Shell.IImageList iml;
    var hres = SHGetImageList((int)iconsize, ref iImageListGuid, out iml);
    var hIcon = IntPtr.Zero;
    hres = iml.GetIcon(iconIndex, ILD_TRANSPARENT, ref hIcon);
    return hIcon;
}

In this code we’re using several API calls. Here’s the tricky part:

First, we need to make call to the SHGetFileInfo function that receives a reference to a structure of type SHFILEINFO, which contains the index of the icon image within the system image list. We will use this index later.

Then we’ve to make is a second call to the SHGetImageList function that receives an output parameter with an IImageList structure, which is modified within the function.

This struct retrieve a COM interface and we need to keep in mind a couple of things:

a) We must use the GUID of this interface in the declaration:

[ComImportAttribute()]
[GuidAttribute(“46EB5926-582E-4017-9FDF-E8998DAA0950”)]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]

b) And in the improbable case you are going to deploy your project over XP, remember that SHGetImageList is not exported correctly in XP. For this reason you must hardcode the function’s entry point. Apparently (and hopefully) ordinal 727 isn’t going to change…

Once we have that COM interface, we only need to call its GetIcon method, passing a parameter with the desired size, and obtaining a handle to the icon by reference.

After having the handle its really simple create an Icon from the handle, and then convert to a Bitmap, BitmapSource or other:


public static System.Drawing.Bitmap GetBitmapFromFilePath(
 string filepath, IconSizeEnum iconsize)
{
    IntPtr hIcon = GetIconHandleFromFilePath(filepath, iconsize);
    var myIcon = System.Drawing.Icon.FromHandle(hIcon);
    var bitmap = myIcon.ToBitmap();
    myIcon.Dispose();
    DestroyIcon(hIcon);
    SendMessage(hIcon, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
    return bitmap;
}

Tip: It’s very important don’t forget to destroy the resources (Icon) when working with the Win32 API!

This method calls the previous one, obtains the icon’s handle and then creates the icon using the handle. Then creates a bitmap from the icon, destroys the icon and returns the bitmap.

I’ve also created an enumeration with the different flags values:

private const int SHGFI_SMALLICON = 0x1;
private const int SHGFI_LARGEICON = 0x0;
private const int SHIL_JUMBO = 0x4;
private const int SHIL_EXTRALARGE = 0x2;
private const int WM_CLOSE = 0x0010;

public enum IconSizeEnum
{
 SmallIcon16 = SHGFI_SMALLICON,
 MediumIcon32 = SHGFI_LARGEICON,
 LargeIcon48 = SHIL_EXTRALARGE,
 ExtraLargeIcon = SHIL_JUMBO
}

Finally, retrieving the icon from a file (inclusive if it’s in a network location) and specify the desired size it’s as easy as:

var size = ShellEx.IconSizeEnum.ExtraLargeIcon;
var ofd = new OpenFileDialog();
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
    labelFilePath.Text = ofd.FileName;
    pictureBox1.Image = ShellEx.GetBitmapFromFilePath(ofd.FileName, size);

}

image

Hope this helps! ;)

Download the source code.

Global Windows Azure Bootcamp

On April 27, something very cool is happening. A bunch of Windows Azure MVP’s and community activists are organizing a Global Windows Azure Bootcamp. This is a completely free, one-day training event for Windows Azure, all organized by the community, and presented in person all over the World.

clip_image001

I’m not sure if this is the largest community event ever – it is very cool to see how many places this event is happening.  Below is the location map as it stands today – and new locations are being added daily. Right now there are almost 100 locations and several thousand attendees already registered to take part.  Browse the location listings to find a location near you.

clip_image003

If you are interested in learning about Windows Azure or want more info, checkout the Global Windows Azure Bootcamp website to learn more about the bootcamps.  Then find a location near you, sign-up and attend the event for free, and get involved with the Windows Azure community near you!

Hope this helps,

Serializar listas genéricas en aplicaciones WinRT

andorraenamora

Edit (11/03/2013): Gracias a una sugerencia del colega MVP Javier Torrecilla se ha modificado el código para especificar el Encoding (UTF8Encoding) y así evitar problemas. Thx dude! :)

 

Hola de nuevo,

Rompiendo un poco con la serie de posts sobre las ‘Parallel Series’, hoy quiero escribir acerca de algo totalmente distinto. Y es que ando haciendo mis pinitos con mi primera aplicación Windows Store, y me estoy encontrando con bastantes cosas que no conozco, y que desde mi absoluto desconocimiento de la plataforma, encuentro bastante tediosas de realizar.

Hoy por ejemplo estaba tratando de almacenar ciertos datos en local -ya que para esta aplicación no quiero depender de ninguna base de datos porque en realidad son cuatro datos- y no he encontrado una forma directa de persistir listas genéricas en el sistema de ficheros local.

Si que es cierto que las herramientas están ahí para ser usadas ‘a mano’, pero he echado en falta una forma más sencilla de hacerlo (que no quiere decir que no exista), de modo que he creado una clase para facilitarme el proceso.

Su propósito es muy específico, pero básicamente permite guardar y leer cualquier lista genérica List<T> a un fichero, que puede ser guardado en la carpeta Local, Temporal o de Roaming.

La clase es la siguiente (aunque supongo que es muy mejorable):

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Windows.Storage;

namespace MySampleApp.Domain
{
    public class LocalStorage<T>
    {
        public List<T> Data { get; set; }
        public string Filename { get; set; }
        public StorageFolder StorageFolder { get; set; }

        public LocalStorage(string filename)
        {
            Filename = filename;
            Data = new List<T>();
            StorageFolder = ApplicationData.Current.LocalFolder;
        }

        public async Task SaveAsync()
        {
            if (!await fileExistAsync(Filename))
            {
                await StorageFolder.CreateFileAsync(
                    Filename, CreationCollisionOption.ReplaceExisting);
            }
            await saveToLocalStorageAsync();
        }

        public async Task<List<T>> LoadAsync()
        {
            if (await fileExistAsync(Filename))
            {
                return await loadFromLocalStorageAsync();
            }
            else
            {
                await StorageFolder.CreateFileAsync(Filename);
                return null;
            }
        }

        public async void DeleteAsync()
        {
            try
            {
                if (await fileExistAsync(Filename))
                {
                    var file = await StorageFolder.GetFileAsync(Filename);
                    if (file != null) await file.DeleteAsync();
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        private async Task<bool> fileExistAsync(string fileName)
        {
            try
            {
                await StorageFolder.GetFileAsync(fileName);
                return true;
            }
            catch
            {
                return false;
            }
        }

        private async Task saveToLocalStorageAsync()
        {
            var sessionFile = await StorageFolder.CreateFileAsync(
                Filename, CreationCollisionOption.ReplaceExisting);
            using (var sessionRandomAccess = await sessionFile.OpenStreamForWriteAsync())
            {
                var serializer = new XmlSerializer(typeof(List<T>), new Type[] { typeof(T) });
                serializer.Serialize(new StreamWriter(sessionStream, new UTF8Encoding()), Data);
                await sessionStream.FlushAsync();
            }
        }

        private async Task<List<T>> loadFromLocalStorageAsync()
        {
            var sessionFile = await StorageFolder.CreateFileAsync(
                Filename, CreationCollisionOption.OpenIfExists);
            if (sessionFile == null) return null;
            using (var sessionInputStream = await sessionFile.OpenReadAsync())
            {
                var reader = XmlReader.Create(new StreamReader(
                    await sessionFile.OpenStreamForReadAsync(), new UTF8Encoding()));
                var serializer = new XmlSerializer(typeof(List<T>), new Type[] { typeof(T) });
                Data = (List<T>)serializer.Deserialize(reader);
                return Data;
            }
        }
    }
}

Y para utilizarla basta con disponer de una lista de objetos de un tipo T:

var customers = new List<Customer>();
customers.AddRange(getSampleCustomers());

Y posteriormente crear una instancia de LocalStorage:

var storage = new MySampleApp.Domain.LocalStorage<Customer>("customers.xml");
//Opcionalmente podemos cambiar la carpeta de destino (por defecto es LocalStorage)
storage.StorageFolder = Windows.Storage.ApplicationData.Current.RoamingFolder;
//Añadimos los datos a persistir
storage.Data.AddRange(customers );
//Guardar los datos al fichero customers.xml
await storage.SaveAsync();
//Recuperar los datos del fichero customers.xml
await storage.LoadAsync();
//Eliminar el fichero customers.xml
storage.DeleteAsync();

Si alguien tiene alguna sugerencia o mejora que no dude en escribir un comentario.

Nos vemos! :)

Problemas de concurrencia

Why concurrent collections?

En un mundo en el que los procesos ya no son secuenciales sino paralelos, es cada vez más posible encontrarnos con problemas de concurrencia al acceder a recursos compartidos. Conceptualmente hablando, esto es algo a los que los desarrolladores ya estamos acostumbrados cuando trabajamos con gestores de bases de datos como Oracle o SQL Server, ya que varios usuarios pueden acceder o modificar la información al mismo.

Sin embargo, la gran mayoría de los desarrolladores pocas veces hemos tenido que lidiar con bloqueos en colecciones en menoria, ya que no todo el mundo crea aplicaciones en las que varios threads acceden a recursos compartidos. De hecho, si alguna vez has lo tenido que hacer sabrás perfectamente que antes de la aparición de la TPL era una de las disciplinas más complejas dentro del desarrollo de software. Algo que favorece la calvície :)

Sin embargo, desde la aparición de la TPL en el .NET Framework 4.0 es mucho más sencillo desarrollar aplicaciones que ejecuten procesos en paralelo o de forma asíncrona, pero esto conlleva que en ocasiones nos olvidemos que hay algunos threads que se ejecutan al mismo tiempo, y esto podría llevar a producir efectos no deseados cuando se trata de acceder a recursos compartidos, como una colección de elementos en memoria.

Por ejemplo: supongamos un escenario en el que tenemos una lista de clientes en memoria y un par de tareas (Task) que acceden a esa colección. La primera tarea podría estar verificando si todos los clientes cumplen una condición X, y si no la cumplen eliminar el cliente de la colección. Mientras tanto la segunda tarea podría estar actualizando alguna propiedad de los clientes, como la edad.

Un escenario real

Encierra este escenario algún peligro? A priori podemos pensar que no. Basta con que la segunda tarea verifique si el cliente existe en la colección antes de actualizarlo. Seguro? Pues no. Al menos no basta si la colección que estamos usando no es una de las nuevas definidas dentro del namespace System.Collections.Concurrent. Y para verlo mejor, hagamos un pequeño ejemplo con código, que es lo que nos gusta a todos.

1 – Partiremos de una clase base Customers con un método que crea n objetos de ejemplo:

public class Customer
{
    public int CustomerId { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }

    public static List<Customer> GetSampleCustomers(int n)
    {
        Random r = new Random(Guid.NewGuid().GetHashCode());
        List<Customer> customers = new List<Customer>();
        for (int i = 0; i < n; i++)
        {
            customers.Add(new Customer()
            {
                CustomerId = i,
                Name = string.Format("Customer {0}", i),
                Age = r.Next(20, 80)
            });
        }
        return customers;
    }
}

2 – A continuación en un formulario declararemos e inicializaremos una colección de tipo Dictionary para almacenar estos objetos cliente:

Dictionary<int, Customer> dic1 = new Dictionary<int,Customer>();

3 – Y en el constructor la rellenamos con 100.000 clientes de ejemplo:

public Form1()
{
    InitializeComponent();
    dic1 = Customer.GetSampleCustomers(100000).ToDictionary(p => p.CustomerId);
}

4 – Ahora, vamos a complicar un poco más el ejemplo y crearemos dos métodos que simulen el borrado y la actualización de los objetos que contiene la colección. Luego llamaremos a éstos métodos para 100 objetos aleatorios de forma paralela para ver que efectos se producen:

private void deleteItem1(int id)
{
    if (dic1.ContainsKey(id) && dic1[id].Age < 30) dic1.Remove(id);
}

private void updateItem1(int id)
{
    if (dic1.ContainsKey(id)) dic1[id].Age++;
}

private void button1_Click(object sender, EventArgs e)
{
    for (int i = 0; i < 100; i++)
    {
        Random r = new Random(Guid.NewGuid().GetHashCode());
        int id = r.Next(1, dic1.Count);
        Task.Factory.StartNew(() => deleteItem1(id));
        Task.Factory.StartNew(() => updateItem1(id));
    }
}

Ejecutamos la aplicación y cuendo pulsemos el botón puede pasar que obtengamos un bonito error como este:

image

Concretamente en la línea que incrementa la edad del cliente:

image

Y digo que puede pasar, pero no es seguro. Tal vez tengamos que repetir el proceso varias veces, y es que en un entorno en el que varios threads acceden a un recurso compartido nada nos asegura que se produzca el error. A veces pasa a la primera y a veces a la cuarta, pero hay que tener presente que cuando esté en producción siempre pasará en viernes por la tarde cinco minutos antes de empezar el fin de semana ;)

Analicemos el porqué del error, por que ¿cómo es posible que no encuentre el elemento en la colección si precisamente en la línea anterior verificamos su existencia? Pues ahí está la gracia, que lo verificamos en la línea anterior. A nosotros -pobres developers- nos parece que la línea anterior en la que verificamos si existe y la línea actual en la que lo emininamos van seguidas una detrás de otra, pero realmente en un entorno asíncrono hay todo un mundo entre ambas. Y eso es porque ambas líneas se ejecutan de forma separada, sin ningún tipo de bloqueo, no existe Transaccionalidad al estilo de las bases de datos, de modo que mientras el primer thread verifica que existe ese elemento en la colección y lo borra, llega el segundo thread y… ZASCA! Lo elimina.

image

El nuevo ConcurrentDictionary

Para estos casos (y muchos otros) aparecen en escena un nuevo conjunto de colecciones especializadas en entornos multithreading. Una de las más populares es una variación del clásico Dictionary, el ConcurrentDictionary. Esta clase proporciona una série de métodos alternativos para agregar, modificar o eliminar elementos llamados TryAdd, TryUpdate o TryRemove. La ventaja de éstos métodos es que son transaccionales y proporcionan Atomicidad. Es decir, garantizan que en caso de que se invoquen, se ejecuten totalmente: O bien se añade/modifica/elimina el elemento de la colección o bien se devuelve el valor False porque no se ha podido realizar la operación. También proporciona un método TryGetValue que intenta obtener un elemento de la colección. Todos estos métodos implementan en su interior bloqueos (lock), para asegurar que nadie más accede al elemento mientras se realiza la operación solicitada.

Un ejemplo real que no falla ;)

Vamos a modificar el ejemplo anterior usando esta nueva colección, para observar su comportamiento en el entorno anterior.

1 – Agregaremos un ConcurrentDictionary después de la declaración del anterior:

ConcurrentDictionary<int, Customer> dic2 =
    new ConcurrentDictionary<int, Customer>();

2 – Lo rellenamos en el constructor, al igual que hacíamos antes. Aquí podemos ver la primera diferencia, ya que usamos uno de los nuevos métodos TryXXX:

Customer.GetSampleCustomers(100000).ForEach(c => dic2.TryAdd(c.CustomerId, c));

3 – A continuación vamos a crear los métodos equivalentes para eliminar y modificar el elemento en la colección:

private void deleteItem2(int id)
{
    Customer c;
    if(!dic2.TryRemove(id, out c)) Console.WriteLine("Error deleting!");
}

private void updateItem2(int id)
{
    Customer c;
    if (!dic2.TryGetValue(id, out c))
    {
        Console.WriteLine("Error getting value");
    }
    else
    {
        Customer newc = new Customer() { CustomerId = c.CustomerId, Name = c.Name, Age = c.Age };
        newc.Age++;
        if (!dic2.TryUpdate(id, newc, c)) Console.WriteLine("Error updating!");
    }
}

En el borrado usamos el método TryRemove que necesita el id del elemento a eliminar, y en caso que lo elimine con éxito, devuelve True y el objeto eliminado en el segundo parámetro out (de salida) del método. En caso que no lo elimine devuelve False y el valor default del objeto a eliminar en el segundo parámetro.

La actualización es un poco más compleja, ya que primero debemos asegurarnos de que el elemento a modificar existe en la colección mediante el método TryGetValue, que básicamente funciona igual que el método TryDelete anterior. Una vez hemos comprobado que dicho objeto existe en la colección creamos una réplica del cliente, modificamos su edad y llamamos al método TryUpdate, el cual se encarga de la modificación.

Es interesante notar que para que la modificación se realice correctamente debemos informar de la clave del objeto en la colección, el nuevo valor del objeto (en este caso la réplica del cliente a la que hemos modificado la edad) y un tercer parámetro que es el valor original del objeto, que es usado para comparar.

4 – Probemos los nuevos métodos en otro botón:

private void button2_Click(object sender, EventArgs e)
{
    for (int i = 0; i < 100; i++)
    {
        Random r = new Random(Guid.NewGuid().GetHashCode());
        int id = r.Next(1, dic1.Count);
        Task.Factory.StartNew(() => deleteItem2(id));
        Task.Factory.StartNew(() => updateItem2(id));
    }
}

Ejecutamos y si vamos a la ventana de consola podremos observar el resultado:

Error getting value
Error getting value
Error getting value
Error getting value
Error updating!
Error getting value
Error getting value
Error getting value

En la mayoría de los casos, obtenemos un error de lectura porque el elemento ya ha sido eliminado de la colección, pero en algunos casos el error se producirá en el método TryUpdate. Eso significa que la llamada a TryGetValue encuentra el elemento, pero cuando lo vamos a modificar éste ya no existe en la colección. Perfecto! :)

Conclusión

La ventaja de usar colecciones específicas en entornos multithreading es clara: Garantizan que el acceso a los recursos compartidos sea transaccional, al más puro estilo de las bases de datos. De acuerdo que su programación sea un poco más compleja, pero no tiene nada que ver con lo que se tenía que hacer antiguamente cuando no existía la TPL.

Por otro lado, el uso de estas colecciones debe hacerse sólo en aquelos casos en los que se accede a recursos compartidos, ya que si no, por un lado estamos complicando nuestro codigo y por otro lado un ConcurrentDictionary no es tan eficiente como lo és un Dictionary, sobre todo en entornos más de escritura que de lectura. Tenéis un post muy detallado al respecto del gran James (aka Black Rabbit) respecto a la diferencia de performance:

http://geekswithblogs.net/BlackRabbitCoder/archive/2010/06/09/c-4-the-curious-concurrentdictionary.aspx

Espero sacar tiempo para otro post en el que explicar otras colecciones de este namespace, como las ‘BlockingCollection’ o las ‘’ConcurrentBag’, que son colecciones más especializadas. La primera está optimizada para escenarios dónde el mismo thread produce y consume objetos, mientras que la segunda ha sido especialmente diseñada para escenarios de productor-consumidor.

Aquí tenéis un pequeño proyecto de ejemplo con el código:

https://www.dropbox.com/s/ej3u3s1v55ltb30/TPL04_Concurrency.zip

Nos leemos! :D

Volver al índice de contenidos

Parallel Series: Tasks, la 8ª maravilla

Nota: Antes de nada quiero disculparme por haber dejado sin publicar en esta serie durante tanto tiempo, de hecho casi un año. Afortunadamente no ha sido ningún problema de salud, si no el tener demasiados frentes abiertos. Ahora que parece que se van cerrando algunos pienso aprovechar para terminar la serie y embarcarme en algún otro nuevo que ya os contaré.

The show must go on

En los posts previos hemos hablado de PLINQ y de la clase Parallel, dos características que facilitan mucho la ejecución de datos en paralelo, sin embargo si alguien me preguntase cual es la característica que más me gusta de la Task Parallel Library lo tendría muy claro: El manejo de tareas asíncronas mediante la clase Task.

Durante muchos años los desarrolladores hemos tenido que lidiar -más ben pelearnos- con la multitarea y la ejecución de código asíncrono. Ya dese las primeras versiones de C# podíamos crear hilos a mano mediante la clase Thread, pero el proceso distaba mucho de ser sencillo y además adolecía de cierta complejidad para manejar cancelaciones o actualizar la interfaz de usuario. Y aunque han habido intentos de mejora como la interfaz IAsyncResult también han aparecido engendros infumables como el BackgroundWorker, el cual es tan malo como hacerse cirugía cerebral con manoplas uno mismo.

Task al rescate!

Así que cuando apareció la TPL y la clase Task los desarrolladores encontramos por fin un método simple y cómodo para ejecutar código asíncrono y además en paralelo. Y esto es realmente muy importante ya que hoy en día en muchas aplicaciones (al menos las que están bien diseñadas) se ejecutan tareas en paralelo para acceder a recursos externos o ‘costosos’, bases de datos, y sobre todo para actualizaciones de la interfaz de usuario. De hecho es tan importante que será una de las mejoras más importantes en la siguiente versión de C# 5.0 de la cual hablaremos al final de la serie.

TaskClass

Actions everywhere

Al igual que la clase estática Parallel y gran parte de la TPL, la clase Task se basa en acciones, de modo que si no las controlas demasiado dale una ojeada al post que publiqué hace un tiempo sobre el tema.

En su sintaxis más básica, se puede utilizar de este modo:

var t = new Task(() => {
    Thread.Sleep(1000);
    Console.WriteLine("A");
    });
t.Start();
Console.WriteLine("B");

O lo que es lo mismo:

Task.Factory.StartNew(() => {
    Thread.Sleep(1000);
    Console.WriteLine("A");
    });
Console.WriteLine("B");

La única diferencia es que en la primera declaramos la variable especificando la acción a ejecutar y luego la ejecutamos explícitamente mediante su método ‘Start’, y en la segunda no utilizamos ninguna variable, sólo especificamos y ejecutamos la acción mediante el método ‘StartNew’ de la clase ‘Task.Factory’.

Observando el código anterior, qué os pensáis que se escribirá primero? A o B? Evidentemente B, ya que podemos imaginar cómo el código no se detiene en el Thread.Sleep(1000) (éste se ejecuta en otro Thread) de modo que ejecuta inmediatamente el print ‘B’. Correcto.

Pero las tareas son mucho más, permiten desde devolver resultados hasta manejar éstas ‘unidades de trabajo’ encadenando tareas a continuación de otras, esperando a que terminen una o un grupo de tareas antes de ejecutar otra, cancelar una tarea o propagar excepciones entre ellas.

1) Devolver un valor desde una tarea…

Como en un método, una tarea puede devolver desde un tipo básico (int, string) hasta cualquier tipo complejo. Para hacer el ejemplo más interesante vamos a utilizar un método que examina la red local en busca de servidores SQL Server y devuelve una lista de strings:

public static List<string> GetSQLServerNames()
{
    List<string> sqlservernames = new List<string>();
    sqlservernames.Add("local");
    SqlDataSourceEnumerator enumSQLServers = SqlDataSourceEnumerator.Instance;
    foreach (DataRow server in enumSQLServers.GetDataSources().Rows)
    {
        if (server["InstanceName"] is System.DBNull)
            sqlservernames.Add(server["ServerName"].ToString());
        else
            sqlservernames.Add(
                string.Format("{0}\\{1}", server["ServerName"], server["InstanceName"]));
    }
    Console.WriteLine("end get servers");
    return sqlservernames;
}

La ventaja de usar este método es que tarda unos segundos en ejecutarse, con lo cual es un candidato perfecto para ser ejecutado de forma asíncrona:

var getServersAsync = new Task<List<string>>(() => GetSQLServerNames());
getServersAsync.Start();
Console.WriteLine("end call");

Si lanzamos este código observaremos que se imprime ‘end call’ inmediatamente, y tarda unos segundos en imprimir ‘end get servers’. Realmente se está ejecutando asíncronamente!

2) …y al terminar continuar con otra tarea

Ahora supongamos que tenemos otro método que se encarga de actualizar la interfaz de usuario  a partir de la lista anterior:

private void updateServersListUI(List<string> servers)
{
    comboBox1.Items.Clear();
    servers.ForEach(p => comboBox1.Items.Add(p));
}

¿No sería lógico que lo hiciese al terminar la tarea anterior? Pues la verdad es que si, y encadenar tareas es algo trivial y que ofrece mucha potencia al desarrollador. De hecho estoy seguro que ya se os ha ocurrido alguna aplicación ;)

Encadenar tareas es tan sencillo como utilizar el método ‘ContinueWith’:

var getServersAsync = new Task<List<string>>(() => GetSQLServerNames());
getServersAsync.Start();
Console.WriteLine("end button2");
getServersAsync.ContinueWith((p) => updateServersListUI(getServersAsync.Result));

Sobre el papel debería funcionar pero no lo va a hacer, ya que hasta ahora no nos hemos fijado en un detalle: En la plataforma .NET no es posible actualizar un control desde otro hilo distinto al que lo ha creado, y toda la interfaz de usuario se crea en el main thread o hilo principal. Y esta limitación todavía existe.

Estableciendo el contexto de ejecución

Antes de la TPL para actualizar la interfaz de usuario desde otro hilo debíamos utilizar el método ‘Invoke’ de la clase ‘Control’, de modo que deberíamos modificar el método anterior de este modo:

private void updateServersListUI(List<string> servers)
{
    if (this.InvokeRequired) this.Invoke(new Action(() =>
    {
        comboBox1.Items.Clear();
        servers.ForEach(p => comboBox1.Items.Add(p));
    }));
}

Pero no va a ser necesario, ya que como parte de la magia de la TPL se nos ofrece la posibilidad de llamar a ‘TaskScheduler.FromCurrentSynchronizationContext’ que nos permite acceder a la interfaz de usuario de forma segura. Así pues lo único que hay que modificar el código anterior es encadenar la segunda tarea usando el contexto de sincronización antes mencionado y olvidarnos de la llamada a Invoke:

getServersAsync.ContinueWith((p) => updateServersListUI(getServersAsync.Result),
TaskScheduler.FromCurrentSynchronizationContext());

Esperando la ejecución de varias tareas

Otra característica muy interesante es la posibilidad de esperar a que termine un grupo de tareas entero, o sólo una de ellas. Supongamos que tenemos unja serie de tareas que se encargan de aplicar unos efectos a una serie de imágenes:

var t1 = Task.Factory.StartNew(
    () => pictureBox1.Image = Properties.Resources.Landscape08.Invert());
var t2 = Task.Factory.StartNew(
    () => pictureBox2.Image = Properties.Resources.Landscape08.Grayscale());
var t3 = Task.Factory.StartNew(
    () => pictureBox3.Image = Properties.Resources.Landscape08.Brightness(140));
var t4 = Task.Factory.StartNew(
    () => pictureBox4.Image = Properties.Resources.Landscape08.Contrast(80));
var t5 = Task.Factory.StartNew(
    () => pictureBox5.Image = Properties.Resources.Landscape08.Gamma(1, 5, 1));
var t6 = Task.Factory.StartNew(
    () => pictureBox6.Image = Properties.Resources.Landscape08.Color(255, 0, 0));

Podría ser interesante no seguir ejecutando el código hasta que la primera termine, o hasta que terminen todas, o hasta que terminen todas pero con un timeout. O sea, que si no terminan todas en 100 milisegundos seguir con la ejecución:

Task.WaitAny(new Task[] {t1, t2, t3, t4, t5, t6});
Task.WaitAll(new Task[] {t1, t2, t3, t4, t5, t6});
Task.WaitAll(new Task[] {t1, t2, t3, t4, t5, t6}, 100);

Otra forma de conseguir esto es mediante la creación de una tarea, especificando que debe esperar a que se complete alguna tarea o todas las especificadas:

var t7 = Task.Factory.ContinueWhenAll(new[] { t1, t2, t3, t4, t5, t6 }, (t) =>
    {
    //DoSomething...
    });

Cancelando tareas

Al igual que en posts anteriores, la clase Task también admite cancelaciones, y a mi juicio suelen ser más utilizadas que sus equivalentes en PLINQ o Parallel, ya que pueden permitir a un usuario cancelar el acceso a un recurso que tarda más de lo previsto (una URL p.e.) y las tareas que debían ejecutarse a continuación.

Partiendo de la base de un método que hace un trabajo largo:

private void DoALongWork(CancellationTokenSource cs)
{
    try
    {
        for (int i = 0; i < 100; i++)
        {
            Thread.Sleep(10);
            cs.Token.ThrowIfCancellationRequested();
        }
    }
    catch (OperationCanceledException ex)
    {
        Console.WriteLine(ex.Message);
    }
}

Podemos cancelar la tarea llamando al método ‘Cancel’ del token:

var cs = new CancellationTokenSource();
var t = Task.Factory.StartNew(
    () => DoALongWork(cs)
    );
Thread.Sleep(500);
cs.Cancel();

Y al cancelarse el código entrará en el catch del método ‘DoALongWork’ en el que se realizarán las acciones apropiadas a la cancelación.

Cancelación y estado

Para terminar, en algunos casos puede ser interesante que en caso de éxito la tarea llame a una segunda, pero en cambio si se cancela llame a una tercera. Para poder hacer esto debemos preguntar por el estado de la primera tarea y realizar un pequeño truco: La excepción no debe ser interceptada en un bloque try!

Así pues el código del método quedaría de este modo (sin try):

private void DoALongWork(CancellationTokenSource cs)
{
    for (int i = 0; i < 100; i++)
    {
        Thread.Sleep(10);
        cs.Token.ThrowIfCancellationRequested();
    }
}

Y la llamada de este otro:

var cs = new CancellationTokenSource();
var t = Task.Factory.StartNew(
    () => DoALongWork(cs)
    );
Thread.Sleep(500);
cs.Cancel();

t.ContinueWith(task =>
    {
        switch (task.Status)
        {
            case TaskStatus.Faulted:
                MessageBox.Show("Fail");
                break;
            case TaskStatus.RanToCompletion:
                MessageBox.Show("Success");
                break;
        }
    }, TaskScheduler.FromCurrentSynchronizationContext());

Como podéis observar, podemos cambiar el flujo del código en función del estado de la tarea.

Importante: Para poder ejecutar este último ejemplo es necesario ejecutar sin depuración (Ctrl+F5)

Bueno, nos hemos dejado algunas cosas en el tintero, pero para no hacer muy largo éste post las veremos más adelante, en otros posts avanzados de la misma serie.

Hasta entonces prometo actualizar la serie con más frecuencia que hasta ahora ;)

Volver al índice de contenidos

Tienes Suscripción MSDN? Pues a publicar en la Store!

Good news!

Acabo de enterarme en tweetland gracias al colega @wasat de que todos aquellos poseedores de una suscripción MSDN (y no me refiero sólo a la ultimate, si no a todas aquellas que incluyen Visual Studio) también disponen de un beneficio adicional:

Se trata de una cuenta para desarrollar aplicaciones y publicarlas en la Windows Store, además de la ya conocida cuenta para publicar aplicaciones para Windows Phone 7. WOW!

msdn01

De este modo, todos aquellos que hemos empezado a hacer nuestras primeras aplicaciones lo tenemos más facil que nunca. Basta con ir al perfil de vuestra suscripción (‘Mi cuenta’ en el menú superior) y verificar si disponéis de la opción Cuenta para desarrolladores de Windows Store, en la que podreis solicitar un código de registro.

msdn_store_account

A partir de aquí, os recomiendo un vistazo a este artículo en el que indicaa cómo registrar el código en la store y aclara algunos de los términos sobre el uso del código de registro, como por ejemplo que de momento sólo se pueden registrar empresas y no desarrolladores:

En este momento solo se pueden registrar cuentas del tipo Empresa. No se podrá completar el registro si selecciona Persona como tipo de cuenta.

Peeeeero que esto no os frene ni un momento… me ha dicho un pajarito que si tenéis lista vuestra aplicación para Windows 8 os podéis poner en contacto con el propio José Bonnin (@wasat) o con la cuenta oficial de MSDN España (@esmsdn) y os ayudarán a pasar un excelence lab y publicar vuestra aplicación en la store.

Así que… Espartanos! A desarrollar! :-D

Nota para Microsoft MVPS: Supongo que todos sabéis que uno de los beneficios de pertenecer al programa es una suscripción Visual Studio Ultimate with MSDN, así que chavales… let’s dev! ;)

Today’s review – Advanced Installer

Hi again guys! :)

Today I’d like to tell you why I decided to change my software deployment method.

ClickonceHell

I’ve spent a lot of time in the last days looking for an alternative way to deploy client applications. During this period I’ve tested different options (including the options provided by Microsoft Visual Studio) and finally I’ve decided to use Advanced Installer.

But before that I wanna tell you why I’ve arrived to this point.

My situation

As a developer I’m still building some Windows applications, because most of these applications are targeted to the business market. And well, until now I’ve been using the typical Setup projects or ClickOnce, depending on each project.

Until now.

Because ClickOnce is not the best solution for complex deployments. It’s quite good for simple or medium scenarios, but is not enough when you need to use merge modules -or equivalent-, database scripts, registry entries, launch conditions, etc.

What about Setup projects? Well, I decided not to use them anymore since I read this post. Because these modules won’t be supported in future versions of Visual Studio. If you haven’t read this post, and you’re still using it, you must read it now.

So, in the previous link you’ve noticed that WiX is recommended instead of Setup projects, but in my opinion WiX is not a valid option, because doesn’t allow neither use designers to customize the installer nor install prerequisites.

For your information: The following table compares the features of Windows Installer Setup Projects, InstallShield 2010 Limited Edition, and the Windows Installer XML Toolset.

Advanced Installer

This application provides a powerful and easy way for making your deployments via Windows Installer plattform, offering different editions: From a freeware with the most common options to an edition for architects, with lots of stunning features like integration with App-V, VMware or System Center deployments.

In my particular case I downloaded a trial version (limited to 30 days) and started to make a test with a medium-size solution, with 20 projects inside. After playing a couple of hours with the tool, I built a complete setup project, including some advanced features like: Merge modules, file associations, launch conditionals (both system and software), prerequisites, registry entries and sql scripts. And of course with complete control over the installation options and the appearance of the setup wizard.

SetupOptions

WOW! Not bad at all… And most of these options are provided by free (not all but most of them).

Coming soon

Now I’m thinking in implement some advanced features, like licensing, trials  and updates. Yes, you can implement a licensing mechanism, and not only in a simply way. You can use your own C++ DLL, or send a POST to a URL to validate the license. It sounds really good!

Another interesting feature when using serial validation allows you to make trial packages. It allows your users to evaluate your product before purchasing, and also enables users to register after they have received a valid key. After the trial period expired the user will be able to run your application only after registration.

Licensing

Finally, my favorite: Advanced Installer provides a way to check for updates. If this option is enabled, before installing the application package, a version check will be executed. If a newer version of the installation package (current MSI) is available it will be downloaded and installed instead of the current one.

My review

A stunning product, with lots of options for making your deployments quickly and easy. You can customize your setup experience in great detail and the UI helps you to create complex installation packages in minutes.

Compared with other market leaders is much easier to use and it has a shortest learning curve.

Sincerly impressed. Good job guys! :)

Advanced Installer website: http://www.advancedinstaller.com/

PS – <IRONIC MODE ON> Ok. I understand traditional Windows applications are from the past, and nowadays everybody is developing web applications or WP7/Metro applications… this kind of developments doesn’t need too complex deployments, and maybe it’s better for everybody the marketplace-based model… But there are a few people that are still developing business applications. I just wanna say… PLEASE MICROSOFT, DON’T FORGET US! :)

Amazing: Awarded MVP of the Year!

mvplogohor

Surprised. Puzzled. Amazed. These are the words that define better my current feelings.

However, while writing these lines I’m just realizing I have a blissful smile, or maybe just a stupid smile. Why? Because I just received an email from Lisa Feigenbaum (Microsoft Community Program Manager) with this message:

“Congratulations on being awarded C# MVP of the Year based on your contributions in 2011!”

WOW! That’s amazing, and sincerely, totally unexpected

For the last 9 years I have been awarded a Microsoft MVP, and believe me, that’s something very important for me. Maybe not for being recognized as an ‘expert’ (it is hard to use that word while there are so damn good people out there), but because they recognize the work of helping the community.

So now, in a private survey all the C# MVPs around the world and the product team have decided to recognize my contributions with the ‘C# MVP of the year’ award, whatever that means.

On the next March 2nd there will be an honorary dinner sponsored by S. Somasegar (“Soma”), Senior Vice President of the Developer Division at Microsoft, with other executives and community leads in the division. Unfortunately, I won’t be able to attend because I come back from Seattle the same day in the morning. Nevertheless I promise you while I am in Seattle I’ll try to have a beer with some of these guys.

From here I’d like to congratulate the rest of the winners (there are 29 in all categories) and thank all my colleagues. Hey people, you’re great!

Kind regards from Andorra,

PS – Next week I´ll start telling you my experiences @ Seattle.