ProgramacioŐĀn AsiŐĀncrona | Trabajando con Delegados Asincronos C#

Se ha venido hablando mucho en los √ļltimos a√Īos sobre la programaci√≥n As√≠ncrona, ya que este esquema de programaci√≥n puede mejorar mucho nuestros programas claro est√° si lo aplicamos correctamente.

En ocasiones nuestros programas nos dan la notificaci√≥n de que el programa no responde o se congela ¬†cuando el usuario interact√ļa con ellos. Esto ocurre porque hay algunas tareas pesadas que se est√°n ejecutando detr√°s, y como s√≥lo hay un hilo de ejecuci√≥n, ¬†entonces no le queda otra opci√≥n ¬†que esperar a que termine dicha tarea para estar nuevamente disponible. Mejorar este tipo de comportamientos les da un toque de profesionalidad a nuestro trabajo algo¬†¬†que siempre es importante.

En esta entrada veremos cómo aplicar la programación asíncrona usando delegados asíncronos, en otra ocasión hace tiempo escribí una entra sobre los delegados la puede leer en el siguiente enlace aquí y otro aquí.

Si con los enlaces no basta para comprender, a continuaci√≥n haremos un peque√Īo ejemplo de c√≥mo funcionan los delegados.

¬ŅQu√© es un Delegado?

Un delegado es la implementación de .NET de los punteros a funciones.

Ahora vamos al ejemplo “suuuuper” sencillo de un delegado.

Primero declaramos un delegado:

  delegate int delegadoProducto(int a, int b);

A continuación creamos una función con la misma estructura del delegado:

public class DelegadoProducto
    {
        public int Producto(int x, int y)
        {
            Console.WriteLine();
            Console.WriteLine("DelegadoProducto.Producto: Calculando el producto de {0} por {1}", x.ToString(), y.ToString());
            Console.WriteLine();
            return x * y;
        }
    }

Ahora instanciamos un objeto de nuestro delegado:

  public static void Main(string[] args)
        {
            // Instanciamos un delegado
            var objDelegado = new DelegadoProducto();
 
            // Asignamos el objeto recién creado a la función que creamos en la clase de apoyo
            delegadoProducto variableDelegadoProducto = new delegadoProducto(objDelegado.Producto);
 
            // Llamamos a la función a través del delegado
            var resultado = variableDelegadoProducto(4, 4);
 
            // Imprimimos el resultado de la ejecución
            Console.WriteLine("Resultado del producto es: {0}", resultado.ToString());
            Console.ReadLine();
        }

Si se fijan Sólo se puede asignar funciones a objetos que tienen la misma estructura que su delegado.

Esta es la salida de nuestro programa en consola en mi caso terminal puesto que estoy usando Mac OS.

Aplicando la programación Asíncrona a nuestros delegados.

Vamos con un ejemplo un poco más elaborado para entender mejor el concepto de llamada síncrona.

Para este ejemplo voy a usar a dos de mis amigas  Naiomi y Maria. Ellas harán un viaje hacia la ciudad de NEW YORK que demora 15 segundos aproximadamente. ( es solo un ejemplo)

El codigo el siguiente:

sing System;
using System.Diagnostics;
 
namespace ProgramacionAsincrona.Delegados
{
    class Program
    {
        delegate int DelegadoViajeNYC(string NombreViajero, Stopwatch temporizador);
 
        static void Main(string[] args)
        {
            // Se instancia un temporizador para calcular el tiempo de ejecución.
            var temporizador = Stopwatch.StartNew();
            
            // Se instancia la clase de apoyo
            var objViaje = new Viaje();
 
            // Se crea el primer delegado, que representará el primer viaje.
            DelegadoViajeNYC viajeNaiomi = new DelegadoViajeNYC(objViaje.ViajeNYC);
 
            // Se crea el segundo delegado, que representará el segundo viaje.
            DelegadoViajeNYC viajeMaria = new DelegadoViajeNYC(objViaje.ViajeNYC);
 
            // Ahora ejecutamos los delegados que harán los viajes
            viajeNaiomi("Naiomi", temporizador);
            viajeMaria("Maria", temporizador);
 
            // Hacemos una pequeña pausa y luego mostramos el mensaje de fin de viajes
            System.Threading.Thread.Sleep(1500);
            Console.WriteLine();
            Console.WriteLine("=> Finalizó las llamadas a los viajes, a los {0} segundos.", temporizador.Elapsed.TotalSeconds.ToString());
            Console.WriteLine();
 
            Console.ReadLine();
        }
    }
 
    public class Viaje
    {
        public int ViajeNYC(string NombreViajera, Stopwatch temporizador)
        {
            Console.WriteLine();
            Console.WriteLine("Inicio de viaje realizado por {0}.", NombreViajera);
            System.Threading.Thread.Sleep(15000);
            Console.WriteLine("Fin de viaje realizado por {0}, a los {1} segundos.", NombreViajera, temporizador.Elapsed.TotalSeconds.ToString());
            return 0;
        }
    }
 
}

Recapitulando

Si eres observador puedes notar que la ejecución del programa es lineal: se llama al primer viaje, cuando éste termina se llama al segundo viaje y cuando éste segundo termina se muestra el mensaje de fin de llamadas de viajes. Esto sucede porque estamos llamando a los delegados de forma síncrona, que es casi lo mismo que llamar directamente a la función. El tiempo total de ejecución de todo el programa es un poco más de 31 segundos.

Realizando llamada asíncrona a un delegado

Cambiamos las líneas 24 y 25 por llamadas asíncronas a los delegados.

            // Ahora ejecutamos los delegados que harán los viajes  (llamadas asíncronas)
            viajeNaiomi.BeginInvoke("Naiomi", temporizador, null, null);
            viajeMaria.BeginInvoke("Maria", temporizador, null, null);

Si ejecutamos nuestro codigo el resultado seria el siguiente:

El programa principal hace las llamadas (asíncronas) a los delegados y sigue su ejecución sin esperar a que estas llamadas terminen. Internamente la ejecución de dichas llamadas sucede en un hilo diferente al hilo del programa principal. Este manejo de hilos es interno, de forma transparente para nosotros.

Conclusiones

Ya puedes imaginar el potencial de esta técnica, cómo implementar este tipo de llamadas para algunos procesos que demanden muchos recursos y poder reducir los tiempos de ejecución dividiendo las tareas a través de llamadas asíncronas. Espero que la apliquen en sus próximos desarrollos.

 

 

 

 

Paso a Paso: .NET Core y Entity Framework Core

Saludos hoy quiero mostrarles como funciona net core fuera de windows yo estare usando MAC OS , pero antes debemos cumplir con una serie de prerrequisitos los cuales son:

OS Prerrequisitos
Windows Windows: Debemos .NET Core SDK for Windows o ambos Visual Studio 2015 Update 3* y .NET Core 1.0 for Visual Studio installedo.
linux, mac o docker Guia para instalar aca  .NET Core

A codear !

  • Paso 1

Abrimos la terminal y escribimos

mkdir sampleefcore
  • Paso 2

Creamos un nuevo proyecto

cd sampleefcore
dotnet new
  • Paso 3

Creamos el archivo de configuración llamado appsettings.json en el cual indicaremos la conexión a la base de datos para este ejemplo usaremos SQLite.

{
  "ConnectionStrings": {
    "Sample": "Data Source=sample.db"
  }
}
  • Paso 4

Ahora modificamos el archivo de proyecto, el cual es el project.json para agregar las dependencias EntityFrameworkCore que especificamos en el archivo appsettings.json

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable",
    "emitEntryPoint": true,
    "copyToOutput": {
      "include": "appsettings.json"
    }
  },
  "dependencies": {
    "Microsoft.Extensions.Configuration": "1.0.0",
    "Microsoft.Extensions.Configuration.Json": "1.0.0",
    "Microsoft.EntityFrameworkCore": "1.0.0",
    "Microsoft.EntityFrameworkCore.Sqlite": "1.0.0"
  },
  "frameworks": {
    "netcoreapp1.0": {
      "dependencies": {
        "Microsoft.NETCore.App": {
          "type": "platform",
          "version": "1.1.0"
        }
      },
      "imports": "dnxcore50"
    }
  }
}
  • Paso 5¬†

Restauramos los paquetes, para ellos ejecutamos el siguiente comando.

dotnet restore
  • Paso 6

Ahora creamos el contexto de EntityFrameworkCore, para ello creamos un archivo y lo llamamos SampleContext.cs y copiamos el siguiente código:

namespace ConsoleApplication
{
    using Microsoft.EntityFrameworkCore;

    /// <summary>
    /// The entity framework context with a Venta DbSet 
    /// </summary>
    public class VentaContext : DbContext
    {
        public VentaContext(DbContextOptions<VentaContext> options)
            : base(options)
        { }

        public DbSet<Venta> Ventas { get; set; }
    }

    /// <summary>
    /// A factory to create an instance of the VentaContext 
    /// </summary>
    public static class VentaContextFactory
    {
        public static VentaContext Create(string connectionString)
        {
            var optionsBuilder = new DbContextOptionsBuilder<VentaContext>();
            optionsBuilder.UseSqlite(connectionString);

            var context = new VentaContext(optionsBuilder.Options);
            context.Database.EnsureCreated();

            return context;
        }
    }

/// <summary>
    /// /// A simple class representing a Venta
    /// </summary>
    public class Venta
    {
        public Venta()
        {
        }

        public int Id { get; set; }

        public string Producto { get; set; }

        public string Caracteristic { get; set; }
    }
}
  • Paso 7

Modificamos el Program.cs con el siguiente código

namespace ConsoleApplication
{
    using System;
    using Microsoft.Extensions.Configuration;

    public class Program
    {
        public static void Main(string[] args)
        {
            // Enable to app to read json setting files
            var builder = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

            var configuration = builder.Build();

            // Get the connection string
            string connectionString = configuration.GetConnectionString("Sample");

            // Create a Venta instance
            var user = new Venta() { Producto = "Soda", Caracteristic = "Pepsi" };

            // Add and Save the Venta in the database
            using (var context = VentaContextFactory.Create(connectionString))
            {
                context.Add(user);
                context.SaveChanges();
            }

            Console.WriteLine($"Product was saved in the database with id: {user.Id}");
        }
    }
}
  • Paso 8

Compilamos nuestra aplicación con el siguiente comando

dotnet build
  • Paso 9

Si todo está bien estamos listos para correr nuestra aplicación.

dotnet run

Fin

Ahora aqui les dejare un peque√Īo video de como funciona ¬†la aplicaci√≥n.

Xamarin y otras especias | Charla

Saludos mi buen amigo¬†Cristopher Junior Vivieca Ramos¬†de ¬†viviecar.com¬†me invito a dar una charla en el Instituto Polit√©cnico Padre Segri en Santiago, Rep. Dominicana. donde estuve hablando sobre “Xamarin y otras especias”

Fotos del evento.

Presentación del evento.

Te gustaria que sea ponente en alguna charla ?

Si te gustaria que diera una charla sobre el mismo tema o otras tecnologías Microsoft no dudes en ponerte en contacto conmigo.

Bug DisplayAlert Xamarin.Forms

Solución para Bug DisplayAlert Xamarin.Forms

Disclaimer: Si alguno considera que no es un bug y es mas una mala pr√°ctica por parte de algunos developers dejo aca el link del bug aca.

Bug

Este sucede cuando implementamos DisplayAlert  en Xamarin.Forms  se traduce en dos ventanas emergentes, lo que obviamente no se espera, y este es el bug.

Estoy hablando de este bloque de código:

var resp = await DisplayAlert("","Seguro quieres salir?","Si", "No");
if (resp)
{ 
   //Hacer algo
}

Solucion

Lo que debemos hacer es  invocar el Display Alert  en el hilo de interfaz de usuario principal usando Xamarin.Forms.Device.BeginInvokeOnMainThread. Tenemos que pasar la acción que  ejecutará el DisplayAlert al hilo principal de la UI:

Device.BeginInvokeOnMainThread(new Action(async () =>
  {
       if(await DisplayAlert("", "Seguro quieres salir?", "Si", "No"))
       {
         //Hacer algo
       }
  }));

Que hace la solución?

Esto soluciona el problema, porque ahora estamos invocando el hilo principal de la interfaz de usuario. Nuestra DisplayAlert ahora se ejecuta solo una vez. Así que, sí, por ahora, podemos utilizar esta solución.

Sin embargo, es de esperar, que corrijan el error, por lo que sólo pueden ejecutar sin el método BeginInvokeOnMainThread. Espero que esto les puede ayudar con su desarrollos.

Si tienen algo que a√Īadir, dudas comentarios no duden en escribirme.

Documentacion: https://developer.xamarin.com/api/member/Xamarin.Forms.Device.BeginInvokeOnMainThread/p/System.Action

Xamarin Diplomado Latinoamérica 3.0

Xamarin Diplomado Latinoamérica 3.0

Microsoft México se anunció una nueva versión del #XamarinDiplomado: Xamarin Diplomado Latinoamérica 3.0, el cual abarcará desde los temas básicos (instalación de herramientas) hasta temas más avanzados, con nuevos speakers y sorpresas.

De momento no se ha dado m√°s informaci√≥n sobre la fecha de inicio y los temas espec√≠ficos del diplomado, pero ya te puedes registrar, dando clic en el siguiente enlace: —>¬†diplomadoxamarin

Xamarin Diplomado es gratis !

Recuerda que el diplomado es gratuito y que aprender√°s muchas cosas nuevas sobre Xamarin, una herramienta que te permite desarrollar aplicaciones m√≥viles multiplataforma que se pueden ejecutar en Android, iOS y Windows 10. Si ya tomaste los diplomados anteriores, contin√ļa con tu formaci√≥n en esta nueva versi√≥n del curso; y si no has comenzado con Xamarin pero te interesa aprender, pues esta es una excelente oportunidad para hacerlo, dado que el curso comenzar√° desde lo b√°sico. Y en espa√Īol.

Entity Framework: Database First | Mi Experiencia

Saludos, recien me enfrasco en una nueva aventura de desarrollo en el mundo web y he decidido usar Entity Framework y pues quise escribir una entrada sobre mi experiencia usandolo en el enfoque Database First.

Que es Database First?

Es el m√©todo que nos permite primero crear la base de datos con sus tablas (y otras estructuras) y luego incorporarlas a la aplicaci√≥n. Esto es necesario cuando la aplicaci√≥n que realizamos necesita utilizar una base de datos existente. Otro uso que podemos darle es cuando necesitamos crear la base de datos, pero nos es m√°s c√≥modo realizar la definici√≥n de las estructuras de la base de datos directamente con sentencias SQL, y luego importar los resultados en la aplicaci√≥n (lo cual en muchos casos es muy √ļtil y necesario, ya que nos permite definir las estructuras SQL tal cual las queremos o las necesitamos) y poder aplicar al 100% todos los tips y orientaciones que podemos encontrar en este blog¬†Base de Datos con SQL Server¬†. Cuando hablamos que podemos crear otras estructuras nos referimos a procedimientos almacenados, funciones, vistas etc…

Una vez sabemos esto vamos a ponerlo en pr√°ctica para ello vamos a crear una peque√Īa base de datos de ejemplo de “estudiantes” la vamos a crear en SQL Server. Las tablas generadas ser√°n:

  • Estudiante
  • Notas
  • Materia

Si eres nuevo y no sabes como crear una base de datos te recomiendo el siguiente video —-> aqui

Para implementar el Database First en nuestra aplicaci√≥n es muy sencillo, lo primero que vamos a hacer es agregar el archivo de Entity Framework a nuestra aplicaci√≥n. En este caso particular lo har√© en un nuevo proyecto de tipo ‚ÄúBiblioteca de clases‚ÄĚ, de forma que quede separada la gesti√≥n de los datos de lo que es la aplicaci√≥n Web en s√≠ (esto implica agregar una referencia desde el proyecto Web al nuevo que estamos creando).

Lo siguiente que haremos es que ¬†agregamos un nuevo elemento de tipo ‚ÄúADO.NET Entity Data Model‚ÄĚ, como se muestra en la imagen. En este caso lo nombraremos EstudiantesDataContext.

 

Una vez que presionemos ‚ÄúAgregar‚ÄĚ, seleccionamos la opci√≥n ‚ÄúGenerar desde la base de datos‚ÄĚ. En un caso normal, no deber√≠amos tener la cadena de conexi√≥n configurada en nuestra aplicaci√≥n, por lo que daremos click en ‚ÄúNueva conexi√≥n‚Ķ‚ÄĚ

Como se ve en la pantalla anterior, debemos ingresar el nombre del servidor, datos de autenticaci√≥n en caso de que sean necesarios y la base de datos que queremos utilizar. Una vez que presionamos ‚ÄúAceptar‚ÄĚ tendremos la confirmaci√≥n de la cadena de conexi√≥n a utilizar.

El siguiente paso  es seleccionar las estructuras de SQL que queremos incluir en nuestra aplicación. Para incluirlas, solo debemos seleccionar el check correspondiente.
Si trabajamos con nombres de tablas en ingles (este no es el caso del ejemplo), el asistente nos ofrece la opción de poner los nombres de las clases en singular, aunque la tabla esté en plural permitiéndonos que el código resultante quede mucho más limpio y representativo de lo que se está modelando con el mismo.

Al presionar ‚ÄúAceptar‚Ä̬†de esa ventana se har√° el mapeo de las estructuras en el DataContext. Para nuestro ejemplo el resultado es el siguiente:

Una vez realizado esto ya podremos utilizar estas clases contenidas en el DataContext.¬†Esto nos permitir√° interactuar directamente con nuestra base de datos. Una de las grandes ventajas que presenta este enfoque es la facilidad de mantenimiento que ofrece. En caso de que haya alg√ļn cambio en las estructuras, solo debemos abrir el archivo del DataContext (con extensi√≥n edmx), hacer click derecho sobre una zona sin clases y seleccionar la opci√≥n ‚ÄúActualizar modelo desde base de datos‚Ķ‚ÄĚ. All√≠ nos aparecer√° una ventana id√©ntica a la de que usamos cuando agregamos las estructuras en primer t√©rmino, pudiendo seleccionar que clases actualizar (tanto porque sean nuevas las tablas, se hayan modificado columnas, o se haya eliminado la tabla):

Estos son los pasos necesarios a seguir para implementar esta técnica.

Opinion personal

Como opinión personal, es recomendable para cualquier tipo de proyectos ya que permite definir nuestras tablas (u otras estructuras) en el motor de base de datos y luego importarlas de forma sencilla. Generalmente este es un orden lógico de trabajo cuando comenzamos una nueva aplicación no ir a escribir codigo directamente.
En los proyectos peque√Īos no tiene desventajas, ya que no requiere mucho tiempo para implementarlo. Y en los proyectos grandes mantiene el orden, ya que distintas personas har√°n modificaciones simult√°neas en la base de datos, las cuales cada uno importar√° en el DataContext cuando sea necesario y f√°cilmente puedes integrar a tu equipo un experto en bases de datos al desarrollo del proyecto.