January 2007 - Artículos

Hola!

Hoy voy a escribir un artículo sobre procesamiento asíncrono en ASP.NET. El escenario planteado es el siguiente: Tenemos una aplicación ASP.NET desde la que necesitamos lanzar un proceso bastante pesado. Es decir, que llevará bastante tiempo terminarlo. Obviamente, si lo invocamos de la manera tradicional, es muy probable que recibamos un error de Timeout en el servidor.

Cuando se presenta una situación como la que describimos, lo primero que se suele venir a la cabeza es lo de siempre: usar hilos. Pero he aquí que estamos desarrollando bajo ASP.NET, en el que los objetos que se crean desde una página se destruyen cuando esa página se termina de procesar, para volver a ser creados en la siguiente petición. Esto quiere decir que si lanzamos un hilo para ejecutar un proceso pesado, hemos de dejarlo corriendo (sin esperar a que termine) para no bloquear el procesamiento de la página si no queremos recibir el error de Timeout.

Esta situación además implica que si queremos saber en qué estado se encuentra nuestro proceso, debemos de ser capaces de consultar el estado desde un objeto diferente (y probablemente desde un hilo diferente también) a aquél que lo haya iniciado.

También hemos de tener en cuenta que se pueden dar varios de estos procesos de forma simultánea, con lo que si queremos consultar el estado de la operación, hemos de identificar de alguna manera a qué operación nos estamos refiriendo.

En este caso, una posible solución sería la siguiente:

Lo primero, podemos crearnos una clase que encapsule el procesamiento pesado que hemos de realizar. Esta clase debe proveer los métodos necesarios para consultar el estado actual del proceso que estamos lanzando. Las ventajas de encapsularlo en una clase es que para lanzar el proceso, podremos crear una instancia de esa clase, dar valores a las propiedades que sean necesarias como datos de entrada del proceso, y arrancar en un hilo aparte el procesamiento llamando a un método de la instancia que acabamos de crear. Si es necesario podemos implementar el interfaz IDisposable si tenemos que liberar recursos al finalizar el proceso.

Lo segundo, podemos crear una clase que haga de repositorio para todos los procesos que se están ejecutando. Para identificar cada una de las instancias de la clase comentada en el apartado anterior, podríamos utilizar un Guid que generaremos al lanzar el proceso. Si estamos utilizando .NET 2.0, podríamos utilizar un Dictionary genérico, con clave de tipo Guid, y usando como tipo del valor la clase comentada en el apartado anterior. Si estamos usando .NET 1.0 ó 1.1, podremos utilizar un Hashtable. Esta clase deberá implementar el patrón Singleton, de manera que podamos acceder a la misma instancia desde la página que queramos, y además implementará los métodos necesarios para facilitarnos la interacción con la colección.

Por último, en la página que inicia el proceso, crearemos una instancia de nuestra clase que encapsula el procedimiento, y generaremos el Guid que lo indentificará en la clase repositorio. Añadimos la instancia al repositorio utilizando dicho Guid, y arrancamos un hilo pasándole el método que hace el trabajo pesado como punto de arranque del hilo.

Después podemos redirigir la respuesta a otra página donde se comprobará el estado de la petición, pasándole a esta página el Guid que hemos generado. O también se podría redirigir a una página que muestre el listado de peticiones pendientes.

Si no estamos usando Ajax, podemos hacer que la página que comprueba el estado del proceso se refresque (si no ha terminado aún) añadiendo una cabecera a la respuesta de la siguiente manera: Response.AddHeader("Refresh", "2")

Si el proceso ha terminado, simplemente quitamos del repositorio la instancia que ha terminado su ejecución (utilizando nuevamente el Guid) - y si implementa el interfaz IDisposable, llamar al método Dispose - y redirigimos a una página que indique que ya hemos terminado la ejecución del proceso.

Bueno, pues esto es todo por hoy... Saludos!

Technorati tags: ,

Hola a todos!

Después de pensármelo desde hace un tiempo, he decidido probar Windows Live Writer para escribir los artículos de este blog. La verdad es que lo estoy probando en el mismo momento que estoy escribiendo esta entrada.

La configuración del Live Writer para utilizarlo con Geeks.ms ha sido de lo más sencilla, y ha recuperado los post anteriores sin ningún problema. Supongo que el hecho de que los propios blogs de MSDN utilicen Community Server (al igual que Geeks.ms) influirá de alguna manera para que esta herramienta funcione tan bien con ellos.

Los pasos a realizar para configurar Live Writer con Geeks son los siguientes:

  • Seleccionar la publicación para otro servicio de Weblog (Another weblog service). Pulsamos Next>.

Paso 1

  • Introducir la URL de la página de inicio del blog, el usuario y el password utilizados para la publicación. Pulsamos Next>.

  • Por último, introducimos el nombre del blog (vendrá relleno con el nombre del blog por defecto), y pulsamos Finish.

Con esto, podremos publicar entradas en el blog usando Windows Live Writer (siempre y cuando estéis leyendo esta misma entrada... ;) )

Saludos!

La tenéis disponible en http://historiasdeunconsultor.blogspot.com/

La periodicidad es semanal, así que más el próximo domingo.

Esta es la última entrada en Geeks acerca de la tira, ya que tiene blog propio.

Saludos!

Publicado 28/1/2007 16:54 por Augusto Ruiz | con no comments
Archivado en:

Microartículo al canto sobre extracción de datos de Excel utilizando ADO.NET. Excitante, ¿verdad?

¿Que no?... Bueno, quizá no tanto, pero como me ha resultado útil, sobre todo para evitar picar datos a mano, y pasarlos a SQL Server... Pues aprovecho y calzo un microartículo.

Lo primero que debemos hacer es hacer nuestros datos accesibles a OleDb. Para ellos, desde Excel, abrimos nuestro fichero excel, y en la hoja en la que tengamos los datos, los seleccionamos, incluyendo las cabeceras de las columnas. Incluir las cabeceras es importante, porque nos darán los nombres de las columnas cuando accedamos al DataTable.

Teniendo los datos seleccionados, vamos al menú Insertar->Nombre->Definir..., (Insert->Name->Define...), y elegimos un nombre para la selección. Este nombre será el que usemos a la hora de hacer nuestra consulta como nombre de tabla.

Una vez hecho esto, guardamos el fichero y cerramos Excel.

En nuestra aplicación C#, lo que debemos hacer es crear una OleDbConnection con la siguiente cadena de conexión:

String sConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Book1.xls;Extended Properties=Excel 8.0;";

Y ya tenemos lista la conexión. Para recuperar los datos, crearemos un OleDbCommand, con una consulta similar a la siguiente:

OleDbCommand objCmdSelect =
      new OleDbCommand("SELECT * FROM NombreAsignadoEnExcel", objConn);

Y con esto, habremos terminado.

Saludos!

Hola!

Este artículo tratará sobre dos temas: Las capacidades de red del Framework de .NET (sin entrar en WCF) y las expresiones regulares. Y para mostrar un ejemplo sencillo de cómo utilizar ambas, vamos a desarrollar un Web Crawler, que no es nada más que una aplicación que tomando como punto de partida una URL, examina la página de dicha URL buscando enlaces, y los sigue para completar un mapa de la web. Este proceso se lleva a cabo de forma recursiva, y para evitar que se quede corriendo indefinidamente le indicaremos la profundidad máxima que puede explorar.

Además, como las páginas pueden tener enlaces comunes, iremos marcando las páginas que ya se han visitado, e incluso podríamos usar un sistema de puntos o pesos para ver qué páginas son las que más enlaces reciben. Esto a una escala mayor, y con un sistema de pesos más complejo (aparte de un análisis del contenido, cosa que no haremos) es básicamente lo que realizan los robots de los buscadores para alimentar sus bases de datos.

Primero vamos a olvidarnos de cómo obtener el HTML de las páginas web (que veréis que es muy sencillo) y vamos a centrarnos en cómo procesarlo para obtener los enlaces y las rutas de los mismos. Aquí es donde entran en juego las expresiones regulares. Utilizaremos dos: Una para detectar los enlaces en el HTML (realmente vamos a buscar los href="...", que aparecen también en CSS, y otros tags), y la otra para procesar URLs.

private Regex urlRegex = new Regex(@"^(?<s1>(?<s0>[^:/\?#]+):)?(?<a1>"
                + @"//(?<a0>[^/\?#]*))?(?<p0>[^\?#]*)" 
                + @"(?<q1>\?(?<q0>[^#]*))?" 
                + @"(?<f1>#(?<f0>.*))?");
 
private Regex hrefRegex = new Regex("href\\s*=\\s*(?:(?:\\\"(?<url>[^\\\"]*)\\\")|(?<url>[^\\s]* ))");

Una vez que tenemos listas las expresiones regulares, podremos obtener todos los href presentes en la página actual. Para seguir avanzando en profundidad, simplemente debemos pedir el recurso al que apunta, y repetir el proceso. De ahí que utilicemos la recursión.

El segundo tema a tratar es cómo pedir las páginas: .NET provee de clases en el namespace System.Net que nos permiten hacer peticiones HTTP de forma sencilla. Nosotros usaremos System.Net.WebRequest, System.Net.HttpWebRequest y System.Net.HttpWebResponse

Un posible uso de estas clases es el siguiente:

HttpWebRequest req = (HttpWebRequest) WebRequest.Create(currentURL); 
HttpWebResponse resp = (HttpWebResponse) req.GetResponse();
if(resp.ContentType.ToLower().IndexOf("text/html") > -1)
{
    Stream istrm = resp.GetResponseStream();
    StreamReader rdr = new StreamReader(istrm);
    string pageHtml = rdr.ReadToEnd();
 
    ...
}
resp.Close();

Podéis ver los detalles de la implementación del crawler en el código del adjunto.

Saludos! 

Bueno... Pues ésta es la novedad que os comentaba. Hace tiempo que lo tenía rondando por la cabeza...

Historias de un consultor

La tira la podréis encontrar en http://historiasdeunconsultor.blogspot.com/index.html

Publicado 21/1/2007 16:10 por Augusto Ruiz | 3 comment(s)
Archivado en:

Hola!

En este blog generalmente escribo artículos técnicos que suelen estar basados en cosas que me encuentro en mis quehaceres diarios. Sin embargo, quiero llevar esto un paso más allá, y por eso se acercan novedades, para compartir también desde un punto de vista diferente mis experiencias en este mundo de la informática. Eso sí, sin abandonar los artículos técnicos :)

Estad atentos... Porque probablemente podáis ver de lo que estoy hablando el próximo domingo, si las cosas no se tuercen... ;)

Saludos!
 

Este va a ser un microArtículo en el que os voy a comentar cómo depurar componentes en tiempo de diseño.
 
A veces, si no tenemos cuidado, al desarrollar componentes podemos encontrarnos con comportamientos no deseados en tiempo de diseño, y no saber qué puede estar causándolos. Para arrojar un poco de luz sobre qué puede estar causando el error, podemos depurar nuestros controles en tiempo de diseño.

¿Cómo?

Es muy sencillo. Supongamos que tenemos abierto una instancia de Visual Studio, donde estamos desarrollando nuestro componente. Hemos de abrir una segunda instancia de Visual Studio. Desde esta segunda instancia depuraremos nuestro componente en tiempo de diseño. Para ello, vamos al menú Herramientas (Tools) y seleccionamos la opción "Procesos de depuración..." (Debug processes...), como en el artículo anterior.

En esta ocasión, el proceso a depurar es el devenv.exe (el propio Visual Studio). Aseguraos de escoger el proceso cuyo título coincida con aquél en el que estáis desarrollando el componente. Además, en la columna Tipo ("Type") deberá aparecer ".NET" (también podrá poner Win32, y puede que alguna otra cosa). En la ventana en la que nos indica qué queremos depurar, aseguraos de que está marcada la opción "Common Language Runtime" (es decir, que queremos depurar código .NET)

Tras esperar un (más o menos largo) momento a que el depurador haya cargado toda la información (dlls, pdbs y demás), abrimos el fichero con el código del componente (directamente, sin abrir el proyecto, sólo el fichero con la clase que nos interesa), y empezamos a poner puntos de interrupción (Breakpoints). Una vez estemos preparados, pasamos a la primera instancia de Visual Studio .NET, y abrimos (o usamos) el componente en tiempo de diseño. En el momento que alcance alguno de nuestros puntos de interrupción, podremos empezar a depurar tranquilamente ;)

Un consejo: Puede ser interesante el cambiar la configuración de las excepciones en la segunda instancia del Visual Studio, de manera que en el momento en el que se lance una excepción (sea manejada o no) se interrumpa la ejecución para poder depurar. Esto se puede hacer en el menú Depuración, seleccionamos Excepciones. En la ventana que aparece, seleccionar las excepciones del CLR, y en los radio buttons que aparecen abajo, marcad "Break Into The Debugger" tanto para las excepciones manejadas como para las lanzadas.

Pues eso es todo por hoy.

Saludos!
 

Hola!

Cuando desarrollamos una aplicación ASP.NET, nos podemos encontrar con la necesidad de depurar código JavaScript para ver si lo hemos implementado correctamente. Con Visual Studio 2003 (y con 2005 también) podemos hacerlo de una forma muy sencilla. En este artículo veremos cómo podemos hacerlo.

Para depurar código JavaScript se puede utilizar el Visual Studio .NET 2003. Antes hay que hacer un par de pasos previos:

  1. Ir al escritorio, botón derecho sobre el icono de Internet Explorer, seleccionar Propiedades (esto es lo mismo que en una ventana del IE ir a Herramientas -> Opciones de Internet).
  2. Seleccionar la pestaña Opciones Avanzadas.
  3. En el árbol que aparece, bajo el apartado Examinar, deseleccionar los checks "Deshabilitar la depuración de secuencias de comandos (Internet Explorer)" y "Deshabilitar la depuración de secuencias de comandos (otros)".

Con esto tenemos configurado el IE para que cuando se produzca un error en Javascript nos pregunte si queremos depurar.

El siguiente paso es abrir el IE, y abrir el Visual Studio 2003. En el menú Herramientas, seleccionar la opción "Procesos de depuración..." (Ctrl+Alt+P)" y en la lista de procesos que aparece, debemos buscar el proceso IEXPLORE.EXE. Si tenemos varios IE abiertos, examinad la columna que indica el título de la ventana (es la tercera, se llama Título).

Seleccionad el proceso a depurar haciendo doble click, y os aparecerá una ventana en la que se puede elegir qué queremos depurar. Aseguraos de que la útlima opción está marcada ("Script"), y para cerrar la ventana del tipo de depuración, pulsad en Aceptar.

El proceso seleccionado se añadirá a la lista inferior de la ventana de la lista de procesos. Podemos cerrar esta ventana pulsando el primer botón de la derecha (Cerrar).

Cuando depuramos el IE, podemos ver una lista de los documentos html que tiene cargados en ese momento y ver el código HTML y JavaScript de los mismos si abrimos la ventana "Documentos en ejecución". Para ello, vamos al menú Depurar, seleccionamos la opción Ventanas, y entre la lista de las ventanas a mostrar seleccionamos "Documentos en ejecución". Normalmente aparecerá en la parte de la derecha, donde está el Explorador de Soluciones. Si hacemos doble click en cualquiera de los documentos HTML que tenga cargados, podremos introducir puntos de ruptura (Breakpoints), y cuando se alcancen, podremos depurar.

Otra opción es la de hacer saltar al depurador cuando nosotros deseemos, sin poner un punto de ruptura explícitamente. Esto se consigue escribiendo "debugger;" (sin las comillas) en nuestro código JavaScript. Cuando a ejecución llegue a esa línea, si estamos depurando el IE, saltará automáticamente al depurador. Ojo, aseguraos de que las llamadas al depurador no estén en la versión final, ya que lo que hace esto es producir una excepción que el depurador entiende. Los usuarios finales verán un mensaje de error en la pantalla si dejamos la línea "debugger;".

Por cierto, esta misma técnica la podemos utilizar para depurar páginas ASP (ojo, ASP del antiguo, no ASP.NET). En este caso, el proceso que tenemos que depurar es inetinfo.exe si la aplicación se está ejecutando con protección de aplicación (App. Isolation) Bajo (se ejecuta en el mismo proceso del IIS). Si usamos otra protección de aplicación, el proceso a depurar será un dllhost.exe, que podremos identificar por la columna Tipo de la lista de procesos (deberá tener un tipo "Script").

Pues esto es todo por hoy. Saludos!

Pablo Álvarez me ha marcado. Con premeditación y alevosía. Y la verdad es que ya quedan pocos a los que marcar... ;)

Así que ahora se supone que tengo que contar cinco cosas sobre mí que la mayoría de la gente desconozca (al menos la gente del plano digital, claro está). Pueeees, ¡vamos allá!

  1. Soy zurdo. Pero zurdo, zurdo. Hago casi todo con la izquierda, y la derecha es más bien la mano tonta. Excepto para el fútbol, que tengo dos piernas derechas (desde la perspectiva de un zurdo, claro).
  2. De pequeño jugaba al balonmano en mi colegio. Era un campeón calentando banquillo, porque como tenía el culo más bien grande, podía calentar dos sitios de una sola vez. Eso y el hecho de ser zurdo hacían que fuese un activo muy cotizado para un equipo de balonmano que perdía casi todos los partidos. :P
  3. Empecé en esto de la informática hace mucho, mucho tiempo en una galaxia... esteeee, no, en Valladolid. Mis padres compraron un Amstrad CPC 464 (sí, de los de cassette, con 64kb de RAM) y, aunque al principio lo usaba únicamente para jugar, poco después, intrigado por lo que hacían mis hermanos, aprendí a programar en BASIC, haciendo un pequeño juego de marcianos 1 contra 1, redefiniendo caracteres (SYMBOL...). Esto sería más o menos cuando tenía 9 años o así.
  4. Durante un buen tiempo fui cantante de un grupo de rock. Como no sabía tocar ningún instrumento, me pusieron ahí, a hacer bulto. Y dimos unos cuantos conciertos en Valladolid. (Tengo pruebas!!!! aquí, aquí y aquí). Poco después de empezar, aprendí a tocar la guitarra (malamente). Ficheros ogg: éste, éste, éste, éste y éste.
  5. También estuve un par de años haciendo un programa de radio en una emisora local de Valladolid, en la que teníamos que pagar para poder hacerlo (3.000 pelas al mes), el programa era semanal, de una hora de duración. Cachondeo, música, y crítica a la música de usar y tirar. Se llamaba Boogie, y era en Onda Verde.

Y para continuar la cadena... Marco a Emilio Calvo, a Bruno González, a Diego García Morate, a José Luis Ramos, y a The ZMan (Andy), que muchos de ellos tienen su blog algo olvidadete... ;)

Saludos!
 

Publicado 8/1/2007 9:49 por Augusto Ruiz | con no comments
Archivado en:

Hola!

Hoy voy a hacer un artículo sobre sincronización de hilos. He visto alguna que otra vez una forma poco correcta de hacer que un hilo padre espere a que su hijo haya terminado (como quedarse en un bucle con un Sleep y comprobar periódicamente si el hilo hijo está vivo), así que voy a explicar una forma muy sencilla de coordinar los hilos.

Como ejemplo podemos usar un servicio de Windows, ya que en estos servicios, la creación de un hilo suele ser casi imprescindible, porque lo normal es que cuando el servicio arranca nosotros generalmente querremos que el servicio se quede activo, pero debemos salir del método OnStart del servicio tan pronto como sea posible para evitar un Timeout en el arranque.

Además, sería interesante que cuando paramos el servicio, en el método OnStop del servicio, el hilo principal espere a que el hilo hijo termine aquello que esté haciendo en ese momento, para no cortar alguna operación que se pueda estar realizando cuando se quiere parar el servicio.

Para conseguir esto, en nuestra clase del servicio podemos declarar un miembro que contenga un WaitHandle en el que almacenaremos si nuestro hilo hijo ha terminado su ejecución. Este WaitHandle es el que usará el hilo padre para esperar al hilo hijo.

Una breve descripción de lo que haremos en el servicio será lo siguiente:

  • Al arrancar el servicio, crearemos un hilo nuevo en el ThreadPool, usando el método QueueUserWorkItem, al que le pasaremos el WaitHandle que hemos definido en la clase. Como WaitHandle es una clase abstracta, podemos usar (por ejemplo) un AutoResetEvent.
  • Al parar el servicio, esperaremos a que el hilo hijo que creamos al arrancar el servicio termine su ejecución. Para ello usaremos el método estático WaitAll de la clase WaitHandle, pasándole como argumento el objeto estático de tipo WaitHandle que usamos al arrancar el servicio.
  • En el método que ejecuta el hilo hijo debemos:
    • Recibir el objeto WaitHandle (AutoResetEvent) que nos pasa el hilo que nos ha creado, y almacenarlo.
    • Agrupar la ejecución del servidor en un bloque try { ... } finally { ... } (se puede-debe poner un catch), y en el finally deberemos notificar que hemos terminado la ejecución, llamando al método Set del objeto AutoResetEvent que hemos recibido, así nos aseguramos de que notificaremos que hemos terminado la ejecución del hilo hijo al hilo padre.

Bueno, pues ésta es la idea básicamente.

Saludos! 

Hola!

Lo primero, feliz año nuevo a todos. (un poco tarde, ¿verdad?)

Hoy voy a tratar un tema un tanto puñetero, que no debería darse nunca en un mundo ideal en el que todo el mundo escribiese código manejado y no hubiese que utilizar componentes COM antiguos hechos con Visual Basic 6 (o cualquier otra tecnología que sea COM y utilice el modelo STA).

¿Por qué los servicios web .NET no se llevan bien con Visual Basic 6? Pues por una razón bastante sencilla. Supongamos que tenemos el escenario propuesto, es decir, un servicio web .NET que utiliza una dll programada con Visual Basic 6. Supongamos también que este servicio se utiliza muy a menudo, de manera que tenemos varias llamadas concurrentes.

Visual Basic 6 utiliza siempre un modelo STA para la generación de sus componentes, y no se puede bajo ningún concepto generar componentes que usen un modelo MTA en Visual Basic 6. Esto quiere decir que cada vez que se realizamos una petición vía COM a un componente desarrollado con Visual Basic 6, esta llamada se ejecutará siempre en el mismo hilo de ejecución. Si se llama varias veces de forma concurrente a dicho objeto, COM encolará las peticiones, ya que un único hilo sólo puede procesar una petición cada vez.

Sin embargo, los servicios web .NET siempre utilizan un modelo MTA (al igual que las páginas aspx en .NET, salvo que utilicemos el atributo AspCompat). Esto quiere decir que para cada petición que realicemos a nuestro servicio, se creará un hilo diferente que llevará a cabo dicha petición. Esto lo podemos comprobar utilizando el siguiente servicio de prueba:

using System;
using System.Web;
using System.Web.Services;
using System.Threading;
 
[WebService(Namespace = "http://tempuri.org/")]
public class ServicioPrueba : System.Web.Services.WebService
{
    [WebMethod]
    public string Prueba()
    {
        return Thread.CurrentThread.ApartmentState.ToString();
    }
}

Ahora pongamos ambos modelos en correspondencia: El WebService usa MTA, y el componente usa STA. En el siguiente diagrama (obtenido del artículo de Jeff Prosise "Running ASMX Web Services on STA Threads") podemos ver cómo se procesan las llamadas a nuestro componente COM:

 MTA -> STA

Si estuviésemos utilizando una página web, podríamos aplicar el atributo AspCompat a la directiva @Page de nuestra página web, consiguiendo que nuestra página se ejecute en un modelo STA. Sin embargo, dicho atributo NO existe para la directiva de los WebServices: @WebService.

¿Qué podemos hacer entonces? En su artículo, Jeff nos propone la siguiente solución: Crear un httpHandler, que herede de System.Web.UI.Page, y que se encargue de procesar las llamadas a los WebServices. El hecho de heredar de Page nos permitirá aprovechar toda la infraestructura creada para soportar el comportamiento que controla el atributo AspCompat (es decir, que tenemos implementado y accesible lo necesario para poder ejecutar nuestro código bajo el modelo STA).

El siguiente diagrama mostraría cómo se procesan las llamadas utilizando el httpHandler propuesto en el artículo:

STA -> STA

Tened en cuenta que esto hay que configurarlo en el web.config para que a la hora de procesar nuestros servicios se utilice el httpHandler. En el artículo lo configura para que este httpHandler se haga cargo de todos los servicios web, y normalmente eso no es lo que necesitamos, así que cuidadín, y a configurarlo correctamente. Por ejemplo, podríamos agrupar los WebServices que deben ejecutarse bajo STA en una ruta concreta, y colocar en esa ruta el fichero web.config que define el httpHandler.

Bueno, pues aquí lo voy a dejar por hoy. Saludos!