Hack-a-thon, repaso a las novedades de networking de Windows Phone 7
Este fin de semana en Málaga se ha celebrado el Hack-a-thon un evento de Microsoft para incentivar el desarrollo de aplicaciones de Windows Phone 7 en entornos universitarios. Es todo un fin de semana de programación de apps y entre medias los desarrolladores pueden elegir las charlas que quieres escuchar. Así que es un agenda dinámica que se decide en base a las valoraciones.
Yo es la segunda vez que participo en un evento de este tipo y en mi caso la charla que me ha tocado es la de Networking. Así que estando ahora mismo en el evento aprovecho para hacer un repaso de las novedades de Windows Phone 7.1 (Mango) en el apartado de comunicaciones.

Peticiones HTTP
Dentro de apartado de peticiones HTTP de toda la vida, WP7 tiene dos clases para realizar este trabajo: WebClient y HttpWebRequest (+Response). Las dos API se distinguen una de la otra por la simplicidad y opciones que ofrecen.
Hay que recordad que todas las comunicaciones en WP7 son asíncronas.
WebClient
WebClient es la API más sencilla para hacer peticiones HTTP, simplemente hay que crear una instancia de esta clase, suscribirse al evento deseado, por ejemplo, DownloadStringCompleted y llamar al método DownloadStringAsync(Uri) para descargarse el contenido de una URI como un string.
public partial class MainPage : PhoneApplicationPage { WebClient client; // Constructor public MainPage() { InitializeComponent(); client = new WebClient(); client.DownloadStringCompleted += new DownloadStringCompletedEventHandler( client_DownloadStringCompleted); } void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { if (e.Error == null) { XElement twitterElements = XElement.Parse(e.Result); var postList = from tweet in twitterElements.Descendants("status") select new TwitterPost { UserImage = tweet.Element("user").Element("profile_image_url").Value, PostText = tweet.Element("text").Value, DatePosted = tweet.Element("created_at").Value }; tweetsListBox.ItemsSource = postList; } } private void loadButton_Click(object sender, RoutedEventArgs e) { string url = "http://twitter.com/statuses/user_timeline/" + nameTextBox.Text + ".xml"; client.DownloadStringAsync(new Uri(url)); } }
En este ejemplo podemos ver como en los argumentos DownloadStringCompletedEventArgs podemos obtener una propiedad llamada Result que contiene el string con el contenido de la petición.
En este tipo de peticiones no podemos añadir cookies ni configurar ningún otro tipo de propiedad para la petición.
Las opciones de personalización son:
-
Añadir cabeceras en la petición y leer las cabeceras de la respuesta.
-
Configurar credenciales para autenticación de usuarios.
-
Permitir la lectura buffereada del contenido de la lectura y de la escritura.
-
Codificación usada para lectura y escritura.
HttpWebRequest
HttpWebRequest es la clase de bajo nivel que permite hacer peticiones HTTP configurando todas las opciones que queramos, es mucho más flexible, pero más complejo de consumir. Estas API utiliza el APM (Asychonous Programming Model) de .NET lo que significa que utiliza para las notificaciones asíncronas IAsyncResult.
Estas son las características:
-
Acceso a todas las cabeceras.
-
Podemos agregar cookies en las peticiones y leer las cookies de respuesta.
-
Podemos especificar el método de la petición (GET o POST)
-
Podemos escribir en el cuerpo de la petición.
Así tenemos un ejemplo completo de peticiones usando HttpWebRequest:
public class ComplexRestRequest : BaseRequestProcessor { public override void ProcessRequest(Uri uri, string body) { content = body; request = HttpWebRequest.Create(uri); request.Method = "POST"; request.Headers["Authorization"] = AuthorizationService.AuthorizationToken.Token; request.Headers["IsComplex"] = "true"; request.BeginGetRequestStream(new AsyncCallback(OnBeginGetRequestStream), null); } private void OnBeginGetRequestStream(IAsyncResult result) { Stream stream = request.EndGetRequestStream(result); byte[] buff = System.Text.Encoding.UTF8.GetBytes(content); stream.Write(buff, 0, buff.Length); buff = null; request.BeginGetResponse(OnBeginGetResponse, null); } private void OnBeginGetResponse(IAsyncResult result) { try { response = request.EndGetResponse(result); string authorizationHeader = response.Headers["Authorization"]; if (!string.IsNullOrEmpty(authorizationHeader)) { AuthorizationService.UpdateAuthorizationToken(authorizationHeader); } string content = null; if (response.ContentLength > 0L) { using (Stream stream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(stream, Encoding.UTF8, true)) { content = reader.ReadToEnd(); } } } FireEndRequestCompleted(new HttpResult(content, false, null)); } catch (Exception ex) { Trace.WriteLine(ex.ToString()); FireEndRequestCompleted(new HttpResult(null, true, ex)); } } private WebRequest request; private WebResponse response; private string content; }
Socket
La siguiente gran funcionalidad de comunicaciones, muy esperada, en Windows Phone 7 son los sockets. Los sockets permiten una comunicación más directa en un canal de comunicación orientado a conexión (TCP) o no orientado a conexión (UDP y multicasting).
Windows Phone 7 soporta direcciones IPv4 pero no soporta IPv6. Toda la API es asíncrona.
Background file transfers
Si tenemos que descargar o subir ficheros al isolated storage de nuestra aplicación, pero queremos que esa descarga se haga cuando el usuario no esté usando la conexión a internet de su dispositivo móvil, podemos usar Background file transfers.
Esta API permite programar la descarga de un fichero al almacenamiento aislado de Windows Phone 7 incluso si nuestra aplicación no está ejecutándose. Soporta HTTP y HTTPS pero no FTP. Alguna de las cabeceras HTTP están reservadas, principalmente las de control de cache.
Estos son los valores de cuota:
-
Tamaño máximo de subida: 5MB
-
Tamaño máximo de descarga sobre 2G/3G: 20 MB
-
Tamaño máximo de descarga sobre WiFi: 100MB
API de información de comunicaciones
Todas las aplicaciones que utilicen recursos online deberán de ser tolerantes a faltas de conectividad por parte del usuario en su dispositivo. Si el usuario está modo avión, no tiene cobertura ni Wifi, la aplicación no debería de fallar y cerrarse, sino que debería de ofrecer la posibilidad de reconectarse de nuevo.
Para eso necesitamos saber cuál es el estado de las comunicaciones del dispositivo.
-
Consulta del operador móvil
-
DeviceNetworkInformation.CellularMobileOperator
-
-
Consulta si hay red disponible
-
DeviceNetworkInformation.IsNetworkAvailable
-
-
Consulta si hay red celular 2G/3G
-
DeviceNetworkInformation.IsCellularDataEnabled
-
-
Consulta si el romaing está habilitado
-
DeviceNetworkInformation.IsCellularDataRoamingEnabled
-
-
Consulta si el WiFi está habilitado
-
DeviceNetworkInformation.IsWiFiEnabled
-
Eligiendo la mejor serialización para aplicaciones móviles
Cuando desarrollamos aplicaciones móviles tenemos que tener en cuenta el tamaño de los datos que enviamos al cliente. Por eso tenemos que elegir la serialización que permite utilizar el menor tamaño para enviar los datos. Aquí tenemos una comparativa de los diferentes formatos para los mismos datos envíados.
| Wire Serialization Format | Size in Bytes |
| ASMX SOAP – DataSet (XML) | 39670 |
| ODATA XML | 73786 |
| ODATA JSON | 34030 |
| REST + JSON | 15540 |
| REST + JSON GZip | 8680 |
Luis Guerrero.
[Artalde.NET] Extensibilidad con MEF y paralelismo con TPL y PLINQ.
El próximo 3 de febrero, miércoles, tendrá lugar la siguiente charla del grupo de usuarios Artalde, esta vez hablando de algunas de las novedades de .NET Framework 4.0 para desarrolladores; una introducción a extensibilidad con MEF y paralelismo con TPL y PLINQ.
El lugar y hora, el de siempre; en la Universidad de Deusto, de 19:00 a 21:00 horas. El registro aquí.
En esta ocasión, será Luis Guerrero el que haga los honores y nos muestre las maravillas que nos trae la versión 4.0 del Framework…cremita de la buena!
Aquí os dejo la descripción completa de la charla:
En esta charlas veremos las novedades de las nos nuevas librerías que Microsoft incluye en .NET Framework para el desarrollo de extensibilidad de las aplicaciones, usado internamente por Microsoft para la extensibilidad de plug-ins en Visual Studio 2010, y cómo afrontar los problemas de concurrencia con Task Parallel Library.
MEF (Managed Extensibility Framework): El Framework de Extensibilidad para componentes administrados es una nueva librería incluida en el .NET Framework 4.0 que permite reutilizar aplicaciones y componentes. Usando MEF, las aplicaciones .NET pueden avanzar de ser estáticamente compiladas a ser dinámicamente compuestas en runtime. Una aplicación MEF está compuesta de Parts que se exportan, se importan y se componen. http://www.codeplex.com/mef/
Parallel Programming in the .NET Framework: Son una serie de nuevas APIs que permiten al desarrollador trabajar con el software y paralelizar los componentes para sacar el máximo partido a toda la potencia que los procesadores de varios cores ofrecen. Veremos TPL (Task Parallel Library) que es la librería para trabajar con Task, que son las nuevas unidades mínimas de paralización (nunca más threads), también veremos PLINQ que nos ofrece que la posibilidad de ejecutar nuestras consultas de LINQ tradicionales en varios cores y con mínimo impacto en la modificación de nuestra query y para finalizar veremos las nuestras estructuras de datos para la programación paralela, como pilas, colas y listas.
Lugar:
Universidad de Deusto
Edificio ESIDE, Aula de videoconferencia (2º piso)
Avda Universidades, 24
48007, BILBAO
Constructores y Finalizadores
Dentro de la orientación a objetos nos encontramos dos tipos de métodos especiales, el constructor y el destructor. En .NET hay dos tipos de constructores de instancia (ctor) y de tipo (cctor) también llamado constructor estático.
Constructores
Cuando un tipo es accedido por primera vez, se ejecuta el constructor estático bajo un doble lock (Como implementar un Singleton concurrente) para asegurar que solamente se llama una vez, si además se está creando una instancia del objeto se llamará al constructor del objeto para inicializarlo. También se llama a todos los constructores base hasta que se llega a System.Object.
Hay que tener en cuenta que el constructor de un objeto no es más que un método que puede aceptar parámetros y que devuelve una referencia sí mismo a this. Como programadores no tenemos que manejar esta situación puesto que el propio compilador la realiza por nosotros.
Hay un caso excepcional en el que podemos crear un objeto pero no obtener una referencia a el nunca, si en el constructor se lanza una excepción. En este caso, el objeto se inicializa, se llama a los constructores base y se aborta el método en el punto en el que se lance la excepción, pero ya se ha reservado memoria para el objeto y nunca podremos acceder a esa referencia de ese objeto a medio construir.
public class Foo { public DateTime DateTime { get; set; } public string file { get; set; } public Foo() { DateTime = DateTime.Now; string[] v = file.Split(','); } }
Aquí tenemos un ejemplo de una clase que en el constructor lanzará una excepción de tipo NullReferenceException, realmente si se ha creado el objeto solo que si hacemos algo como:
Foo f = new Foo();
Nunca llegaremos a obtener la referencia del objeto hay creado y además tenemos que tener en cuenta que se tendrá que recolectar el objeto para liberar memoria en la siguiente recolección de basura.
Es por eso que hay que tener mucho cuidado con lo que se pone en el constructor porque podemos dejar a nuestro tipo inutilizado.
La situación se agrava si se lanza una excepción en el constructor de tipo, ya que no podremos acceder a ninguna variable estática ni crear instancias de este tipo.
Destructores o finalizadores
Los destructores (o finalizadores) son los métodos que se llamarán cuando el objeto ya no es usado y se reclama la memoria usada. En este caso es el CLR el que se encarga de llamar a este finalizador pues nosotros no tenemos ningún mecanismo para liberar un objeto.
Un finalizador se define de esta manera:
~Foo()
{
Console.WriteLine("Adiossss !!");
}
Eso significa que cuando esa instancia del tipo Foo sea recolectada se ejecutará este método. Si miramos al IL generado por este programa realmente el destructor ha pasado a llamarse Finalize() y está marcado como virtual.
Además de definir un destructor de clase hay otro mecanismo para poder definir un destructor, implementando la interfaz IDisposable. Este es el único mecanismo que tiene un programador de .NET para poder definir un destructor de objeto y además poder llamarlo el mismo de codigo de usuario.
Para evitar que este método sea llamado otra vez por el CLR existe el método GC.SupressFinalize.
¿Cómo es llamado este método?
Cada vez que se realiza una recolección de basura el GC examina todos los objetos y si encuentra alguno que es finalizable, es decir, tiene destructor o implementa IDisposable, entonces ese objeto que está listo para ser recolectado pasa a la cola de finalización.
Cuando los objetos están en esa cola de finalización un Thread de alta prioridad se encarga de sacar un elemento de la cola, ejecutar su finalizador y marcarlo como listo para ser recolectado.
Consideraciones a tener en cuenta:
· Cuando el objeto está listo para ser finalizado se lleva a la cola de ReadyToFinalize y además todos los objeto de su grafo son marcados. Eso significa que si ese grafo de objeto normalmente moriría en esta recolección, ahora es promovida a la siguiente, simplemente porque su objeto raíz es finalizable.
· Las generaciones más viejas son recolectadas menos que las generaciones más jóvenes lo que indica que nuestro grafo de objetos puede permanecer vivo durante mucho tiempo hasta que es completamente finalizado y recolectado.
· Al utiliza un único thread, aunque está en prioridad alta, puede darse el caso de que el si tenemos una maquina con 32 procesadores y solamente tenemos una finalizado objetos la cola pueda crecer mucho.
· Hay que tener mucho cuidado con lo que se ejecuta en el finalizador porque si se produce una excepción el proceso entero se descarga. No estamos hablando de que se descargue el dominio de aplicación sino todo el proceso.
Garantías de finalización:
· Durante la ejecución normal de la aplicación y durante cada recolección de basura, se llamara a los finalizadores de los objetos que haya en la cola.
· Si el proceso termina sin la coordinación del CLR, llamando a TerminateProcess o ExitProcess, el CLR tendrá su primera noticia de que el proceso se está cerrando cuando se envíe el mensaje DLL_PROCESS_DETACH en el DllMain. Así que el CLR no tiene tiempo de hacer nada y lo único que puede pasar es que termine los finalizadores críticos (CriticalFinalizerObject).
· Si el proceso es cerrado con el pleno conocimiento del CLR, llamado a Exit o Enviroment.Exit, se finalizarán los objetos que están en la cola de finalización y los finalizadores críticos. Pero los posibles objetos que salgan de una recolección de basura listos para ser finalizados se quedarán sin ser finalizados.
· Si se descarga el dominio de aplicación entonces solamente se finalizarán los objetos que estuvieran en la cola de finalización y los finalizadores criticos.
El codigo del ejemplo: http://www.luisguerrero.net/downloads/ctor.zip
Saludos. Luis.
Remote Desktop Services en Windows Server 2008 R2
Durante la semana pasada estuve liado montando un servidor en mi casa, como podréis imaginaros le instale la última versión de Windows Server, Windows Server 2008 R2 que solamente está en 64bits.
Quería hacer dos cosas con el servidor, montar un Media Center Extender para mi Xbox360 y tener Hyper-V para mis maquinas virtuales. Al final he instado un Windows 7 32bits, virtualizado para HomeGroup, Media Center Extender y demás. La otra máquina virtual es otro Windows Server 2008 R2 con Visual Studio Team Foundation 2010 Beta 1 con Sql Server 2008.
Una vez que lo he tenido todo montado he estado curioseando entre los roles de Windows Server y me ha llamado la antecion el de Remote Desktop Services, ya que había leído mucho sobre el tema pero nunca lo había visto en funcionamiento.
La idea es básica, hacer que nuestro servidor de aplicaciones funcione como tal, pero a través de escritorio remoto, pero no como un escritorio remoto completo sino virtualizando solamente la ventana de la aplicación remota y enviándola al cliente.
Lo que me ha gustado es lo fácil que ha sido configurarlo en Windows Server 2008 R2 y la fantástica integración que tiene Windows 7.
Aquí podéis ver una captura del rol instalado en Windows Server 2008 R2, en la rama de RemoteApp Manager podéis pulsar en Add RemoteApp Programs.
Estos programas son solo programas instalados en el servidor, así que para mis cosas he instalado Office 2007 y Visual Studio 2010 que lo podéis ver en la lista.
Además disponemos de una aplicación web que nos permite lanzar las aplicaciones en nuestro ordenador simplemente haciendo un clic.
Y por último lo que podéis ver aquí es la integración de Windows7 con la lista de aplicaciones de servidor, en el que me dice que tengo 21 aplicaciones disponibles para usar, es básicamente un feed que la aplicación web que viene en Windows Server expone para que Windows 7 consuma.
Saludos. Luis.
[Conferencia] Desarrollo de aplicaciones para Microsoft Surface en DevDays09
Hola a todos, el 18 y 19 de Febrero en Portugal se celebra el DevDay09 de Microsoft en la cual voy a dar con mi compañero Ricardo una charla sobre desarrollo de aplicaciones en Microsoft Surface, así que si estáis por la zona nos veremos allí.
Saludos. Luis.
WUX203 - Desenvolvimento Aplicações para Microsoft Surface
Datos:
Instituto Superior Técnico
Campus do TagusPark
Porto Salvo
Que hacer con un proyector y un grupo de amigos
Pues eso, nos han regalado un proyecto en mi casa, y con la terraza que hay en mi casa que íbamos ha hacer?, pues jugar el RockBand y al Guitar Hero, aquí os dejo algunas fotos del evento, :p
Para los que no lo sepáis, vivo en Madrid y ahora con el frio que hace ha sido curioso jugar así. Espero encontrar algo parecido en Londres!!
Saludos. Luis.
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.
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.
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.
Windows Vista con UAC gentileza de mi colega Pedro Laguna
Y este es mi escritorio sin UAC con IE8 Beta2 con varios tabs y el process explorer abierto.
