<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Angel "Java" Lopez : Concurrency and Coordination Runtime</title><link>http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx</link><description>Tags: Concurrency and Coordination Runtime</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Web Crawler distribuido usando AjMessages</title><link>http://msmvps.com/blogs/lopez/archive/2009/03/10/web-crawler-distribuido-usando-ajmessages.aspx</link><pubDate>Tue, 10 Mar 2009 01:07:04 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1677100</guid><dc:creator>lopez</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1677100</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/03/10/web-crawler-distribuido-usando-ajmessages.aspx#comments</comments><description>&lt;p&gt;En Enero pasado, actualicé mi proyecto AjMessages para que soporte comunicación usando DSS/CCR&amp;nbsp;y Windows Communication Foundation. AjMessage puede ejecutarse de forma distribuida, enviando mensajes desde un nodo lógico a otro. Los nodos lógicos pueden albergarse en una o más máquinas física. Más información sobre AjMessages en:&lt;/p&gt; &lt;p&gt;&lt;a title="AjMessages- a message processor" href="http://ajlopez.wordpress.com/2007/10/18/ajmessages-a-message-processor/"&gt;AjMessages- a message processor&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ajlopez.wordpress.com/2008/10/08/distributed-applications-with-ajmessages-using-dssccr/" target="_blank"&gt;Distributed Applications with AjMessages using DSS/CCR&lt;/a&gt;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/10/10/aplicaciones-distribuidas-con-ajmessages-usando-dss-ccr.aspx" target="_blank"&gt;Aplicaciones Distribuidas con AjMessages usando DSS/CCR&lt;/a&gt;&lt;br /&gt;&lt;a title="AjMessages- hacia un procesador de mensajes" href="http://msmvps.com/blogs/lopez/archive/2007/10/22/ajmessages-hacia-un-procesador-de-mensajes.aspx"&gt;AjMessages- hacia un procesador de mensajes&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Pueden descargar el código fuente desde&lt;/p&gt; &lt;p&gt;&lt;a title="ajmessages" href="http://www.codeplex.com/ajmessages"&gt;http://www.codeplex.com/ajmessages&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Tenía la idea de escribir un procesador de mensajes distribuidos. Hace unos años, escribí mi primer intento, llamado AjServer&lt;/p&gt; &lt;p&gt;&lt;a title="Hacia el AjServer" href="http://msmvps.com/blogs/lopez/archive/2006/07/20/105318.aspx"&gt;Hacia el AjServer&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Luego, encontré al proyecto &lt;a title="Fabriq" href="http://ajlopez.wordpress.com/2007/10/14/remember-fabriq/"&gt;Fabriq&lt;/a&gt;, estudiando sus ideas e implementación. En ese proyecto,&amp;nbsp;hay manejadores (handlers) lógicos de mensajes, que pueden instalarse de modo distribuido, de forma transparente, cambiando la información de configuración:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/fabriq01.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;En el&amp;nbsp;2007, escribí la primera versión de AjMessages, como prueba de concepto: pude reproducir bastante de las ideas de Fabriq, y a la vez, elevar el nivel de abstracción de algunos puntos, para conseguir mayor flexibilidad. Fabriq estaba más orientado a SOA. AjMessages se orienta a mensajes arbitrarios, que coordinados, pueden funcionar en una aplicación en grilla.&lt;/p&gt; &lt;p&gt;La solución actual de AjMessages es:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/AjMessages01.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Hay un proyecto núcleo, y dos proyectos de transporte: uno para soporte de WCF, y otro que se basa en DSS/CCR (tecnologías de Microsoft Robotics). Si no tienen DSS/CCR instalado, pueden remover los proyectos que lo referencia. El núcleo de AjMessages está lib de dependencias de esas tecnologías.&lt;/p&gt; &lt;p&gt;AjMessages.SampleApp contiene un simple manejador de mensajes: un decrementador de enteros, que toma un mensaje de entrada, con un contenido entero, lo decrementa, y produce un nuevo mensaje.&lt;/p&gt; &lt;p&gt;En cambio,&amp;nbsp;AjMessages.WebCrawler implementa&amp;nbsp;el mensaje y manejadores de mensajes para armar un web crawler distribuido. Pueden ejecutarlo desde una sola máquina, o en varias.&lt;/p&gt; &lt;p&gt;Cara AjMessages tiene:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Body&lt;/strong&gt;: un contenido arbitrario&lt;br /&gt;&lt;strong&gt;Headers&lt;/strong&gt;: información adicional, por clave/valor.&lt;br /&gt;&lt;strong&gt;Action&lt;/strong&gt;: describe el destino del mensaje, usando un patrón Aplicación/Nodo/Acción&lt;/p&gt; &lt;p&gt;(más detalle en &lt;a title="AjMessages- a message processor" href="http://ajlopez.wordpress.com/2007/10/18/ajmessages-a-message-processor/"&gt;&lt;a title="AjMessages- hacia un procesador de mensajes" href="http://msmvps.com/blogs/lopez/archive/2007/10/22/ajmessages-hacia-un-procesador-de-mensajes.aspx"&gt;AjMessages- hacia un procesador de mensajes&lt;/a&gt;&lt;/a&gt;)&lt;/p&gt; &lt;p&gt;Exploremos el ejemplo de web crawler. Esta aplicación está compuesta de nodos, que pueden ser orquestado para visitar una página web, tomar de esa página todos los enlaces relacionados, y volver a tomar esas páginas. Para que no sea un proceso infinito, la visita de páginas se limita al sitio inicial, y hasta un nivel de profundidad. La aplicación puede ser descripta lógicamente con este diagrama:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/webcrawler01.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;El primer mensaje se envía al nodo Controller, a su acción Dispatch. Ese primer mensaje contiene la dirección de la página a visitar. El mensaje es enriquecido, y pasado al nodo Controller, acción Resolve. Este nodo está a cargo de mantener la lista de páginas ya visitadas, y de controlar la profundidad de exploración. Si el enlace recibido es aprobado, entonces el mensaje es enviado al nodo Downloader, acción Download. El contenido de la página es recuperado, agregado al mensaje, y reenviado al nodo Harvester, a su acción&amp;nbsp;Harvest. Esta acción analiza el contenido de la página, y emite&amp;nbsp;varios mensajes, uno por&amp;nbsp;cada enlace encontrado. El receptor de esos nuevos enlaces es el nodo Resolver, en su acción Resolve. Así, el proceso continua hasta visitar todas las páginas (con un límite en la profundidad a explorar).&lt;/p&gt; &lt;p&gt;Esta aplicación se puede describir en un archivo de configuración XML, como por ejemplo:&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:a3a0de01-755f-4538-96e5-153042196cee" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;?&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;AjMessages&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;WebCrawler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Dispatcher&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;DispatcherHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages.WebCrawler.Handlers.Dispatcher, AjMessages.WebCrawler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Action &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Dispatch&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Handler&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;DispatcherHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Harvester&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;HarvesterHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages.WebCrawler.Handlers.Harvester, AjMessages.WebCrawler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Action &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Harvest&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Handler&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;HarvesterHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Downloader&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;DownloaderHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages.WebCrawler.Handlers.Downloader, AjMessages.WebCrawler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Action &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Download&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Handler&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;DownloaderHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Controller&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ResolverHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages.WebCrawler.Handlers.Resolver, AjMessages.WebCrawler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Action &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Resolve&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Handler&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ResolverHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;AjMessages&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Un aplicación, entonces, está compuesta de nodos lógicos. Cada nodo puede ser visto como una clase lógica. Cada nodo puede manejar acciones, que son los puntos destinos de los mensajes. Una acción puede&amp;nbsp;estar compuesta de uno o varios pasos. Este es el punto de extensibilidad de la aplicación: deben proveer los pasos, el manejador de mensaje, y escribir el archivo de configuración que orquestre el procesamiento de los mensajes.&lt;/p&gt;
&lt;p&gt;Pero una cosa es la aplicación, y otra es su distribución en máquinas físicas. Pueden tener dos hosts, e instalar diferentes nodes en cada uno:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/webcrawler02.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;En este diagrama, el Dispatcher y el Resolver están en un hosts, mientras que el Downloader y el Harvester están en otro. Pero Uds. pueden poner Harverstes en cada hosts,&amp;nbsp;o en veinte máquinas.&amp;nbsp;Queda en&amp;nbsp;Uds. cómo distribuir la carga del trabajo. Cuando un mensaje&amp;nbsp;es enviado&amp;nbsp;a un destino (Aplicación/Nodo/Acción),&amp;nbsp; AjMessage lo reenvía a un host apropiado, que contenga un nodo capaz de procesar el mensaje.&lt;/p&gt;
&lt;p&gt;La distribución de nodos lógicos en un host físico se define via configuración, por ejemplo:&lt;/p&gt;
&lt;p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:17c1d13e-1e21-4d39-a87d-3e3a2b0a07a4" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;?&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;AjMessages&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Host &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Server1&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Address&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;http://localhost:50002/AjMessages&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Activate&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Administration&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;WebCrawler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Controller&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Dispatcher&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Harvester&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Downloader&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Host&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;

  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Host &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Server2&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Address&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;http://localhost:50003/AjMessages&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Administration&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;WebCrawler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Dispatcher&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Harvester&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Downloader&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Host&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;AjMessages&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Ejecutando el ejemplo Web Crawler&lt;/h3&gt;
&lt;p&gt;Pueden probar el programa, lanzando dos hosts, en la misma máquina. Hay que ejecutar el programa de consola AjMessage.Console. Al comenzar esta aplicación, podemos ingresar el comando&lt;/p&gt;
&lt;p&gt;&lt;font face="Consolas"&gt;fork&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Este comando lanza un segundo host. Ahora, podemos configurar los dos hosts. En el primero, ingresamos:&lt;/p&gt;
&lt;p&gt;&lt;font face="Consolas"&gt;load ConfigurationServer1.xml&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Este archivo carga la aplicación AjMessage inicial (es una aplicación más dentro de &amp;quot;la grilla&amp;quot;), y define un endpoint WCF para escuchar mensajes de otros posibles hosts. Ahora, en la misma consola, ingresamos:&lt;/p&gt;
&lt;p&gt;&lt;font face="Consolas"&gt;load ConfigurationWebCrawler.xml&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Este comando carga la definición de la aplicación Web Crawler, con sus nodos lógicos (no hay información de deploy todavía). El tercer comando, define la distribución física de hosts:&lt;/p&gt;
&lt;p&gt;&lt;font face="Consolas"&gt;load ConfigurationWebCrawlerNode1.xml&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Ahora, volvamos a la segunda consola. Ahí, ingresamos los comandos:&lt;/p&gt;
&lt;p&gt;&lt;font face="Consolas"&gt;load ConfigurationServer2.xml&lt;br /&gt;load ConfigurationWebCrawler.xml&lt;br /&gt;load ConfigurationWebCrawlerNode2.xml&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Estamos listos para lanzar el primer web crawling. Vamos a la primera consola, e ingresamos:&lt;/p&gt;
&lt;p&gt;&lt;font face="Consolas"&gt;send WebCrawler/Dispatcher/Dispatch &lt;/font&gt;&lt;a href="http://ajlopez.zoomblog.com"&gt;&lt;font face="Consolas"&gt;http://ajlopez.zoomblog.com&lt;/font&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;El programa comienza a trabajar, en AMBAS consolas. Una típica salida de la primera consola:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/webcrawler03.png" alt="" /&gt; &lt;/p&gt;
&lt;h3&gt;Próximos pasos&lt;/h3&gt;
&lt;p&gt;Debería arreglar algunos problemas en el transporte DSS/CCR (actualmente, puede ejecutar una aplicación simple como el decrementador de enteros, pero no con el web crawler). Dos puntos para implementar:&lt;/p&gt;
&lt;p&gt;- Configuración remota de nodos&lt;br /&gt;- Distribución de los manejadores de mensajes (sus&amp;nbsp;.dlls)&amp;nbsp;a los nodos&amp;nbsp;remotos&lt;br /&gt;- Una configuración para todos los nodos (ahora, cada nodo es configurado separadamente)&lt;/p&gt;
&lt;p&gt;Comencé un experimento con un proceso más abstracto de mensajes, que quisiera que pudiera implementar casos de uso como:&lt;/p&gt;
&lt;p&gt;- Un simple hello world&lt;br /&gt;- El ejemplo de decrementar enteros&lt;br /&gt;- Web crawler distribuido&lt;br /&gt;- Una especie de Enterprise Service Bus&lt;/p&gt;
&lt;p&gt;Pueden ver mis primeros pasos en:&lt;/p&gt;
&lt;p&gt;&lt;a title="http://code.google.com/p/ajcodekatas/source/browse#svn/trunk/AjProcessor" href="http://code.google.com/p/ajcodekatas/source/browse#svn/trunk/AjProcessor"&gt;http://code.google.com/p/ajcodekatas/source/browse#svn/trunk/AjProcessor&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Todavía en desarrollo.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1677100" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjMessages/default.aspx">AjMessages</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Decentralized+Software+Services/default.aspx">Decentralized Software Services</category></item><item><title>Aplicaciones distribuidas con AjMessages usando DSS/CCR</title><link>http://msmvps.com/blogs/lopez/archive/2008/10/10/aplicaciones-distribuidas-con-ajmessages-usando-dss-ccr.aspx</link><pubDate>Fri, 10 Oct 2008 11:42:46 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1650446</guid><dc:creator>lopez</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1650446</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/10/10/aplicaciones-distribuidas-con-ajmessages-usando-dss-ccr.aspx#comments</comments><description>&lt;p&gt;Por ahora, es solo un proyecto en marcha. La aplicación de ejemplo es mínima. Pero es la evolución de mi trabajo anterior con AjMessages usando&amp;nbsp; Windows Communication Foundation:&lt;/p&gt; &lt;p&gt;&lt;a title="AjMessages- a message processor" href="http://ajlopez.wordpress.com/2007/10/18/ajmessages-a-message-processor/"&gt;AjMessages- a message processor&lt;/a&gt;&lt;br /&gt;&lt;a title="AjMessages- hacia un procesador de mensajes" href="http://msmvps.com/blogs/lopez/archive/2007/10/22/ajmessages-hacia-un-procesador-de-mensajes.aspx"&gt;AjMessages- hacia un procesador de mensajes&lt;/a&gt;&lt;/p&gt; &lt;p&gt;El año pasado excribí ese ejemplo, y otro que usaba DSS/CCR. Solo el primero fue publicado, ahora, estuve revisando mi implementación con DSS/CCR, tecnologías que son la base de &lt;a href="http://www.microsoft.com/robotics" target="_blank"&gt;Microsoft Robotics&lt;/a&gt;. El código nuevo se puede bajar del repositorio de&amp;nbsp;CodePlex en:&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.codeplex.com/ajmessages" href="http://www.codeplex.com/ajmessages"&gt;http://www.codeplex.com/ajmessages&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Los ejemplos estan basados en ideas del proyecto &lt;a href="http://ajlopez.wordpress.com/2007/10/14/remember-fabriq/" target="_blank"&gt;Fabriq&lt;/a&gt;, ahora en nuevas tecnologías. En estos días, &lt;a href="http://blogs.msdn.com/asehmi" target="_blank"&gt;Arvindra Sehmi&lt;/a&gt; escribió sobre una nueva versión de Fabriq, llamada Fabriq4Dss, que está usando DSS/CCR como base. Preparó una presentación para la conferencia JAOO, lean:&lt;/p&gt; &lt;p&gt;&lt;a title="JAOO 2008 Presentation" href="http://blogs.msdn.com/asehmi/archive/2008/10/03/jaoo-2008-presentation.aspx"&gt;JAOO 2008 Presentation&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Espero que pronto aparezcan novedades sobre esa implementación y otras. Keep tuned!&lt;/p&gt; &lt;h3&gt;La solución&lt;/h3&gt; &lt;p&gt;Tiene tres proyectos:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajmessages2008sln.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;El primero es la implementación del núcleo del sistema, que es independiente del transporte de los mensajes distribuidos:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajmessages2008prj1.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;El segundo proyecto contiene un ejemplo con un message handler que decrementa un entero. El tercer proyecto es un DSS Service Component que se usa para albergar el servidor de AjMessages en una máquina con un DSS Host:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajmessages2008prj2.png" alt="" /&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Para una más detallada explicación de qué es una aplicación, mensaje, servidor, leer mis anteriores posts:&lt;/p&gt; &lt;p&gt;&lt;a title="AjMessages- a message processor" href="http://ajlopez.wordpress.com/2007/10/18/ajmessages-a-message-processor/"&gt;AjMessages- a message processor&lt;/a&gt;&lt;br /&gt;&lt;a title="AjMessages- hacia un procesador de mensajes" href="http://msmvps.com/blogs/lopez/archive/2007/10/22/ajmessages-hacia-un-procesador-de-mensajes.aspx"&gt;AjMessages- hacia un procesador de mensajes&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;La aplicación&lt;/h3&gt; &lt;p&gt;Un archivo de configuración XML define las aplicaciones a ejecutar. Una aplicación tiene:  &lt;ul&gt; &lt;li&gt;&lt;strong&gt;Nodes&lt;/strong&gt;: una colección de acciones a procesar (un nodo tiene varias acciones, podría ser análogo a clase/método).  &lt;li&gt;&lt;strong&gt;Handlers&lt;/strong&gt;: objetos que procesan mensajes. Un handler puede estar compuesto de otros handlers.  &lt;li&gt;&lt;strong&gt;Actions&lt;/strong&gt;: puntos con nombre para entrar a un handler &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Un ejemplo de definición de aplicación en&amp;nbsp;AjMessages.SampleApp\Configurations\Server1.xml:  &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:a9f878a1-2449-441f-99ea-2736884f0b42" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;?&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;AjMessages&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Administration&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ConfigureHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages.ConfigureHandler, AjMessages&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;PrintHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages.PrintHandler, AjMessages&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;PrintMessageHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages.PrintMessageHandler, AjMessages&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ConfigurePipeline&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;PrintHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
          &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Text&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Value&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Reconfiguring server...&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ConfigureHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Action &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Configure&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Handler&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;ConfigurePipeline&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;

  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;App1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Node1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;PrintMessageHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages.PrintMessageHandler, AjMessages&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;PostHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages.PostHandler, AjMessages&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;DecrementHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Type&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages.SampleApp.Handlers.DecrementHandler, AjMessages.SampleApp&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Pipeline1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;DecrementHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;PostHandler&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
          &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Action&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Value&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;App1/Node1/Process&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Handler&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Action &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Process&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Handler&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Pipeline1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Node2&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;

  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Host &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Server1&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Activate&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Administration&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;App1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Node1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Node2&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Host&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;

  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Host &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Server2&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; Address&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;http://localhost:50002/ajmessages/node&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;AjMessages&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Administration&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;App1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Node1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Node &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Node2&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Application&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Host&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;AjMessages&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Ejecutando el ejemplo&lt;/h3&gt;
&lt;p&gt;Abrimos la solución en el Visual Studio 2008 (se necesita&amp;nbsp;tener instalado un&amp;nbsp;Microsoft Robotics Developer Studio, una versión&amp;nbsp;CTP de este año, debe configurar el directorio de salida de los proyectos para que apunten a su directorio de MRDS). Al ejecutar el proyecto DSS se lanza un DSS Host, que muestra una ventana de control:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajmessages2008contr1.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;El host está ejecutando en las puertas 50000/50001. Configure el servidor AjMessages usando el archivo AjMessages.SampleApp\Configurations\Server1.xml.&lt;/p&gt;
&lt;p&gt;Podemos lanzar un segundo host desde el prompt de DSS:&lt;/p&gt;
&lt;p&gt;&lt;font face="Consolas"&gt;bin/dsshost /p:50002 /t:50003 &lt;br /&gt;m:&amp;lt;pathto&amp;gt;\Source\AjMessages.DssServices\AjMessagesDssServices.manifest.xml&lt;/font&gt; 
&lt;p&gt;Un segundo formulario aparece: 
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajmessages2008contr2.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Use el archivo de configuración AjMessages.SampleApp\Configurations\Server2.xml&amp;nbsp;y el port&amp;nbsp;50002.&lt;/p&gt;
&lt;p&gt;Podemos enviar un mensaje a la aplicación de ejemplo (que ejecuta en dos hosts). El mensaje es solamente un entero, que es decrementado en cada proceso de acción en cada nodo. El nodo de decremento está instalado en ambos servidores, así que el mensaje viaja de uno a otro durante su proceso.&lt;/p&gt;
&lt;h3&gt;Próximos pasos&lt;/h3&gt;
&lt;p&gt;Quiero mejorar varios puntos. Me gustaría serializar cualquier tipo de mensaje, ahora solamente viajan enteros y strings. Me gustaría usar un solo archivo de configuración, en lugar de uno por máquina. Y poder tener en una sola solución, ambas implementaciones de hosting y transporte: DSS/CCR y WCF.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1650446" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjMessages/default.aspx">AjMessages</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Decentralized+Software+Services/default.aspx">Decentralized Software Services</category></item><item><title>CCR usado en mensajes asincrónicos</title><link>http://msmvps.com/blogs/lopez/archive/2008/09/19/ccr-usado-en-mensajes-asincr-243-nicos.aspx</link><pubDate>Fri, 19 Sep 2008 10:09:36 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1648290</guid><dc:creator>lopez</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1648290</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/09/19/ccr-usado-en-mensajes-asincr-243-nicos.aspx#comments</comments><description>&lt;p&gt;Leo en el blog de &lt;a href="http://blogs.msdn.com/asehmi/" target="_blank"&gt;Arvindra Sehmi&lt;/a&gt; que la gente de &lt;a href="http://www.swhouse.com/home/default.aspx" target="_blank"&gt;Tyco Software House&lt;/a&gt; implementó un sistema donde usando &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc163556.aspx" target="_blank"&gt;CCR&lt;/a&gt; (Concurrent and Coordination Runtime), la librería que viene dentro de &lt;a href="http://www.microsoft.com/robotics"&gt;Microsoft Robotics&lt;/a&gt;. En su artículo &lt;a title="ARCast.TV - Nice Example of CCR Adoption in the Enterprise" href="http://blogs.msdn.com/asehmi/archive/2008/09/18/arcast-tv-nice-example-of-ccr-adoption-in-the-enterprise.aspx"&gt;ARCast.TV - Nice Example of CCR Adoption in the Enterprise&lt;/a&gt;&amp;nbsp;muestra el video donde la gente de Tyco explica cómo consiguieron procesar gran cantidad de mensajes, basándose en envío asincrónico. &lt;/p&gt; &lt;p align="center"&gt;&lt;iframe src="http://channel9.msdn.com/shows/ARCast.TV/413356/player/" frameborder="0" width="320" scrolling="no" height="325"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;a href="http://channel9.msdn.com/shows/ARCast.TV/ARCastTV-Stephen-Tarmey-of-Tyco-on-adopting-Robotics-Studio-CCR-for-High-Performance-Async-IO/"&gt;ARCast.TV - Stephen Tarmey of Tyco on adopting Robotics Studio CCR for High Performance Async IO&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Me gustaría que mostraran algo más gráfico del sistema que armaron, pero igual es interesante escuchar a alquien que usa a Microsoft Robotics aplicado a la empresa.&lt;/p&gt; &lt;p&gt;Ya Arvindra había comentado usos de DSS/CCR más allá de Robotics en&lt;/p&gt; &lt;p&gt;&lt;a title="DSS Use Cases in the Enterprise" href="http://blogs.msdn.com/asehmi/archive/2008/06/12/ccr-dss-use-cases-in-the-enterprise.aspx"&gt;DSS Use Cases in the Enterprise&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Todavía algunos de esos usos no están publicados, pero espero que aparezcan más casos de éxito con el tiempo.&lt;/p&gt; &lt;p&gt;El año pasado escribí y publiqué un ejemplo AjMessages, con intercambio de mensajes asincrónicos, usando WCF como comunicación entre nodos de una grilla:&lt;/p&gt; &lt;p&gt;&lt;a title="AjMessages- hacia un procesador de mensajes" href="http://msmvps.com/blogs/lopez/archive/2007/10/22/ajmessages-hacia-un-procesador-de-mensajes.aspx"&gt;AjMessages- hacia un procesador de mensajes&lt;/a&gt;&lt;/p&gt; &lt;p&gt;También el año pasado escribí una versión para usar CCR internamente, y DSS como comunicación entre los nodos, pero no la publiqué. El núcleo del sistema se puede implantar en un host WCF o en un host DSS. Me gustaría en estos días, pulir un poco el código, y publicar el ejemplo, para ver que uno puede usar CCR internamente para encolar mensajes en memoria, y repartirlos en un pool de threads que maneja internamente CCR, mientras al mismo tiempo, repartimos mensajes en otros nodos de la grilla, si los hubiera, sin mayor problema, para conseguir escalabilidad usando más máquinas de forma transparente. Como ejemplo de uso, podría reescribir el Web Crawler o el programa de Fractal, que escribí directamente para DSS/CCR/VPL:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/06/23/agentes-distribuidos-y-fractales-usando-dss-vpl.aspx" target="_blank"&gt;Agentes Distribuidos y Fractales usando DSS/VPL&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/06/20/agentes-distribuidos-usando-dss-vpl.aspx" target="_blank"&gt;Agentes Distribuidos usando DSS/VPL&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Pero imaginen que pueden repartir una tarea entre varias máquinas, incluso remotas. Imaginen que pueden enviar una tarea a realizar (como recolectar información para un informe de Business Intelligence) a una sucursal, y otra tarea a máquinas de otra sucursal dentro de su empresa. Pueden recibir los resultados como mensajes, usando un patrón del tipo request-response. Podemos codificar &amp;quot;agentes&amp;quot; que se envíen mensajes entre sí, para colaborar en un objetivo.&lt;/p&gt; &lt;p&gt;Creo que el modelo de mensaje asincrónico junto con la implementación de grilla, puede ser explotado de muchas maneras. Mi idea es aprovechar mi semana sabática (que comienza mañana) para codificar algunos proyectos, y uno de ellos es una versión más terminada de AjMessages.&lt;/p&gt; &lt;p&gt;Nos leemos!&lt;/p&gt; &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1648290" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjMessages/default.aspx">AjMessages</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Decentralized+Software+Services/default.aspx">Decentralized Software Services</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Microsoft+Robotics+Developer+Studio/default.aspx">Microsoft Robotics Developer Studio</category></item><item><title>Recursos de Microsoft Robotics Developer Studio</title><link>http://msmvps.com/blogs/lopez/archive/2008/09/10/recursos-de-microsoft-robotics-developer-studio.aspx</link><pubDate>Wed, 10 Sep 2008 13:17:43 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1647339</guid><dc:creator>lopez</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1647339</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/09/10/recursos-de-microsoft-robotics-developer-studio.aspx#comments</comments><description>&lt;p&gt;En estos días, estuve dando varias charlas sobre Microsoft Robotics Developer Studio (MRDS), quisiera escribir acá sobre lo que presento en esas charlas, y enlaces a recursos del tema.&lt;/p&gt; &lt;p&gt;En primer lugar, pueden ver todo sobre el producto de Microsoft desde:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msdn.microsoft.com/es-ar/robotics/default(en-us).aspx" target="_blank"&gt;Microsoft Robotics&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Ahí encontraran para bajarse el &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=57CE326B-2125-4163-A33F-ED2F69E03B56" target="_blank"&gt;Microsoft Robotics Developer Studo 2008&lt;/a&gt; (actualmente CTP July), y &lt;a href="http://msdn.microsoft.com/robotics/aa731520" target="_blank"&gt;descargas adicionales&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;La presentación original de la charla es la que dio&amp;nbsp;Arvindra Sehmi en el Regional Architect Forum de México:&lt;/p&gt; &lt;p&gt;&lt;a title="Mexico Regional Architect Forum 2008" href="http://blogs.msdn.com/asehmi/archive/2008/05/03/mexico-regional-architect-forum-2008.aspx"&gt;Mexico Regional Architect Forum 2008&lt;/a&gt;&lt;/p&gt; &lt;p&gt;En el blog de Arvindra, pueden encontrar información adicional sobre el uso de MRDS en la industria, más allá de robótica:&lt;/p&gt; &lt;p&gt;&lt;a title="DSS Use Cases in the Enterprise" href="http://blogs.msdn.com/asehmi/archive/2008/06/12/ccr-dss-use-cases-in-the-enterprise.aspx"&gt;DSS Use Cases in the Enterprise&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Mi presentación en español, la pueden bajar de my Skydrive:&lt;/p&gt; &lt;p&gt;&lt;a href="http://cid-9f903f3d6db0c176.skydrive.live.com/self.aspx/Presentations/Robotics200803-2003.ppt" target="_blank"&gt;Presentación de Microsoft Robotics&lt;/a&gt; (14 megas)&lt;/p&gt; &lt;p&gt;En la charla muestro algunas de las ideas&amp;nbsp;y ejemplos de diseño, implementación y tecnologías usadas en MRDS:&lt;/p&gt; &lt;h3&gt;Decentralized Software Services&lt;/h3&gt; &lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;" src="http://www.ajlopez.com/images/articles/roboticsdss.png" align="left" alt="" /&gt; Basado en principios de diseño de REST (Representational State Transfer), es la base que tiene MRDS para operar en forma distribuida de forma eficiente. Usa estándares de la industria, como HTTP para el envío y recepción de mensajes, XML y SOAP para el protocolo de transporte. Todo MRDS se basa en tener un host (servidor) de DSS (el DssHost) que levanta servicios. Los servicios son los elementos que nosotros programamos. Dentro del software viene ya servicios provistos, para manejar e interactuar con robots simulados y reales, y con cámaras, sensores, motores, y otros elementos, como ventanas y joysticks. Los servicios se comunican entre sí usando DSS. Podemos manejar uno o varios robots, desde una o varias máquinas. O podemos, como muestra la imagen, ver el estado de un servicio, como una cámara de video, apuntando en nuestro browser a la dirección donde se encuentra el servicio (puede ser nuestra máquina u otra máquina). &lt;h3&gt;Concurrent and Coordination Runtime&lt;/h3&gt; &lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;" src="http://www.ajlopez.com/images/articles/roboticsccr.png" align="left" alt="" /&gt; Otra de las novedades del sistema, es una nueva librería que simplifica&amp;nbsp;y potencia el uso de mensajes para comunicar distintas partes de nuestra aplicación. Podemos enviar un mensaje a un Port, y dentro de ese&amp;nbsp;Port podemos programar cómo atendemos a ese mensaje. Toda la atención de los mensajes se maneja de una forma eficiente, usando múltiples hilos de ejecución, y un manejo interno nuevo de lo que se llama un pool de threads. Es interesante explorar las capacidades de CCR, que se puede usar como librería desde fuera de MSRS. Podemos armar sistemas compuestos de componentes que se envíen mensajes asincrónicos entre sí. Los componentes pueden residir todos en el mismo programa y máquina, o podemos usar DSS para que los mensajes viajen entre distintos servidores.&lt;/p&gt; &lt;h3&gt;Visual Programming Language&lt;/h3&gt; &lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;" src="http://www.ajlopez.com/images/articles/roboticsvpl.png" align="left" alt="" /&gt; Teniendo un servidor de servicios DSS, los servicios se pueden programar en el Visual Studio, o pueden coordinarse los servicios a usar, detallando los mensajes y su proceso, usando el Visual Programming Language, una forma de conectar esos servicios de forma visual. Usando un diseñador interactivo, arrastrando y soltando servicios, y conectando sus mensajes de salida y entrada, podemos modelar un programa, un nuevo servicio, que por ejemplo conecte nuestro joystick o ventana de control, con robots, dispositivos u otros servicios. Uno de los ejemplos que muestro, es cómo interactuar con un servicio de Text to Speech (texto a voz).&lt;/p&gt; &lt;p&gt;&amp;nbsp; &lt;h3&gt;Simulation Environment&lt;/h3&gt; &lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;" alt="" src="http://www.ajlopez.com/images/articles/roboticssim2.png" align="left" /&gt;No necesitamos tener un robot físico para interactuar. MRDS nos brinda un entorno de simulación, para manejar entidades (poliedros, esferas, entidades complejas como mesas, paredes, robots). &lt;p&gt;El entorno de simulación es otro servicio más, que se levanta dentro de un host de DSS. Nuestros servicios pueden enviarle mensajes, como &amp;quot;crear suelo&amp;quot;, &amp;quot;crear cielo&amp;quot;, &amp;quot;crear sol&amp;quot;, &amp;quot;agregar entidad esfera&amp;quot;. Las entidades tienen características, que incluyen densidad, peso, cómo las afecta la gravedad. &lt;p&gt;Este entorno de simulación está basado en tres tecnologías, que se instalan (si no las tiene ya instaladas) con el MRDS: el DirectX 9, el Microsoft XNA (para el render de 3 dimensiones), y el AGEIA PhysX que simula la física del entorno. Estas tecnologías pueden ejecutarse basadas en software, o pueden aprovechar hardware especial que tenga instalada la máquina: tarjetas de video con soporte de 3D, o plaquetas de simulación física. &lt;p&gt;Como todo servicio, el entorno de simulación puede ejecutar en una máquina, y el resto de los servicios estar repartido en otros servidores de la red. Por ejemplo, pueden colocar varios robots en un entorno de simulación, y cada uno manejarlo desde una máquina dedicada. &lt;h3&gt;Robochamps&lt;/h3&gt; &lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;" src="http://www.ajlopez.com/images/articles/robochamps01.png" align="left" alt="" /&gt; Es un sitio donde aparece desafíos a resolver con MRDS, donde programadores de todo el mundo pueden participar resolviendo un problema. El primer concurso fue ganado por Dave Sprague, entusiasta de robótica de los EE.UU., y Jackson Matsuura, profesor de Brasil. En el Desafío Amazed compitieron participantes de 77 países. Ahora se abre el &lt;a href="http://www.robochamps.com/rc/Common/challenge.aspx?id=Sumo" target="_blank"&gt;desafío Sumo&lt;/a&gt;&amp;nbsp;donde dos robots, en un ring, tiene que maniobrar para echar al otro fuera de la arena.&lt;/p&gt; &lt;p&gt;Encontraran videos explacativos (en inglés) sobre las tecnologías que se usan en MRDS, así como ejemplos para bajarse.&lt;/p&gt; &lt;h3&gt;Enlaces&lt;/h3&gt; &lt;p&gt;En la charla menciono algunas implementaciones de gente de la comunidad, involucrada en robótica, y que usa MRDS. &lt;/p&gt; &lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;" src="http://www.wimobot.com/ThumbImage.aspx?width=150&amp;amp;height=142&amp;amp;src=http://www.wimobot.com/Images/Pics/Lego%20Wimo%20001.jpg" align="left" alt="" /&gt; Como el sistema puede ejecutarse en un Windows Compact Edition, se puede instalar en un dispositivo de Windows Mobile. Eso es lo que Brian Cross, con su:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.wimobot.com/"&gt;http://www.wimobot.com/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;WiMoBot es el Windows Mobile Robot. Usa un Windows Mobile 5.0 SmartPhone como el cerebro central de control. Cross lo ha extendido para poder ser manejado remotamente desde una PC usando MRDS. Hay una versión montada sobre el lego NXT en:&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.wimobot.com/AssemblyNxt.aspx" href="http://www.wimobot.com/AssemblyNxt.aspx"&gt;http://www.wimobot.com/AssemblyNxt.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;como el sistema operativo &lt;/p&gt; &lt;p&gt;Raúl Arrabales Moreno está trabajando desde hace tiempo, en Inteligencia Artificial y robótica. Pueden visitar su sitio de&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.conscious-robots.com/" href="http://www.conscious-robots.com/"&gt;http://www.conscious-robots.com/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Está trabajando con MRDS, del que destaca sus características de manejo de concurrencia, coordinación, mensajería asincrónica. Está usando MRDS son el robot Pioneer 3DX, uno de los robots reales y simulados soportados por el sistema. Encontraran ahí foros sobre robótica&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.conscious-robots.com/en/researchers-and-associations/discussion-forums/www.conscious-robots.com-f.html" href="http://www.conscious-robots.com/en/researchers-and-associations/discussion-forums/www.conscious-robots.com-f.html"&gt;http://www.conscious-robots.com/en/researchers-and-associations/discussion-forums/www.conscious-robots.com-f.html&lt;/a&gt;&lt;/p&gt; &lt;p&gt;como&lt;/p&gt; &lt;li&gt;&lt;a href="http://www.conscious-robots.com/en/researchers-and-associations/discussion-forums/psyche-b-discussion.html"&gt;PSYCHE-B Discussion Forum&lt;/a&gt; &lt;li&gt;&lt;a href="http://www.conscious-robots.com/en/researchers-and-associations/discussion-forums/psyche-d-discussion-forum-theoretical-emph.html"&gt;PSYCHE-D Discussion Forum (Theoretical emphasis)&lt;/a&gt; &lt;li&gt;&lt;a href="http://www.conscious-robots.com/en/researchers-and-associations/discussion-forums/language-mind-and-consciou.html"&gt;Language Mind and Consciousness&lt;/a&gt; &lt;li&gt;&lt;a href="http://www.conscious-robots.com/en/robotics-studio/robotics-studio-forums/conscious-robots.com-forum-for-msrs-eng.html"&gt;Conscious-Robots.com Forum for MSRS (English)&lt;/a&gt; &lt;li&gt;&lt;a href="http://www.conscious-robots.com/en/robotics-studio/robotics-studio-forums/conscious-robots.com-forum-for-msrs-spa.html"&gt;Conscious-Robots.com Forum for MSRS (Spanish)&lt;/a&gt;&amp;nbsp;(muy recomendable, con abundante información, preguntas y respuestas de los participantes) &lt;li&gt;&lt;a href="http://www.conscious-robots.com/en/robotics-studio/robotics-studio-forums/msrs-official-forums.html"&gt;MSRS Official Forums&lt;/a&gt; &lt;li&gt;&lt;a href="http://www.conscious-robots.com/en/robotics-studio/robotics-studio-forums/robocup-msrs-challenge-mai.html"&gt;Robocup MSRS Challenge Maillist&lt;/a&gt;&lt;/li&gt; &lt;h3&gt;Posts y ejemplos&lt;/h3&gt; &lt;p&gt;Post que escribo sobre Robótica en general,&amp;nbsp;a partir de:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/tags/Rob_26002300_243_3B00_tica/default.aspx" target="_blank"&gt;Posts sobre Robótica&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Algunos de los ejemplos que muestro en la charla:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/06/23/agentes-distribuidos-y-fractales-usando-dss-vpl.aspx"&gt;Agentes Distribuidos y Fractales usando DSS/VPL&lt;/a&gt;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/06/20/agentes-distribuidos-usando-dss-vpl.aspx"&gt;Agentes Distribuidos usando DSS/VPL&lt;/a&gt;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/06/11/int-233-rprete-tipo-lisp-usando-dss-y-vpl.aspx"&gt;Intérprete tipo Lisp usando DSS y VPL&lt;/a&gt;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/05/28/ejemplo-de-web-crawler-usando-dss-decentralized-software-services.aspx"&gt;Ejemplo de Web Crawler usando DSS (Decentralized Software Services)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/04/28/scribble-distribuido-con-microsoft-robotics-developer-studio-y-dss.aspx"&gt;Scribble Distribuido con Microsoft Robotics Developer Studio y DSS&lt;/a&gt;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/04/13/algoritmos-gen-233-ticos-con-ajagents-y-concurrency-and-coordination-runtime-ccr.aspx"&gt;Algoritmos Genéticos con AjAgents y Concurrency and Coordination Runtime (CCR)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Más enlaces sobre estos temas en:&lt;/p&gt; &lt;p&gt;&lt;a href="http://delicious.com/ajlopez/msrs"&gt;http://delicious.com/ajlopez/msrs&lt;/a&gt;&lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/dss"&gt;http://delicious.com/ajlopez/dss&lt;/a&gt;&lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/ccr"&gt;http://delicious.com/ajlopez/ccr&lt;/a&gt;&lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/robotics"&gt;http://delicious.com/ajlopez/robotics&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Nos leemos!&lt;/p&gt; &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1647339" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Rob_26002300_243_3B00_tica/default.aspx">Rob&amp;#243;tica</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Decentralized+Software+Services/default.aspx">Decentralized Software Services</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Microsoft+Robotics+Developer+Studio/default.aspx">Microsoft Robotics Developer Studio</category></item><item><title>Charla gratuita de Microsoft Robotics</title><link>http://msmvps.com/blogs/lopez/archive/2008/07/18/charla-gratuita-de-microsoft-robotics.aspx</link><pubDate>Fri, 18 Jul 2008 18:23:51 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1641369</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1641369</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/07/18/charla-gratuita-de-microsoft-robotics.aspx#comments</comments><description>&lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;" src="http://www.ajlopez.com/images/articles/roboticssim.png" align="left" alt="" /&gt; El&amp;nbsp;lunes 28 de Julio daré una charla gratuita en el &lt;a href="http://www.clubdeprogramadores.com/" target="_blank"&gt;Club de Programadores&lt;/a&gt;, sobre Microsoft Robotics, acá en Buenos Aires.&lt;/p&gt; &lt;p&gt;La idea es presentar la herramienta y su modelo de programación. Visitaremos el entorno de simulación, el manejo de robots simulados (que pueden reemplazarse por robots reales), el Visual Programming Language, y las librerías Decentrilized Software Services (DSS), y Concurrent and Coordination Runtime (CCR).&lt;/p&gt; &lt;p&gt;Más informes e inscripción a esta charla gratuita en:&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.clubdeprogramadores.com/cursos/CursoMuestra.php?Id=458" href="http://www.clubdeprogramadores.com/cursos/CursoMuestra.php?Id=458"&gt;http://www.clubdeprogramadores.com/cursos/CursoMuestra.php?Id=458&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Ya escribí algo sobre estos temas en este blog:&lt;/p&gt; &lt;p&gt;&lt;a title="Rob&amp;oacute;tica" href="http://msmvps.com/blogs/lopez/archive/tags/Rob_26002300_243_3B00_tica/default.aspx"&gt;Robótica&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="Decentralized Software Services" href="http://msmvps.com/blogs/lopez/archive/tags/Decentralized+Software+Services/default.aspx"&gt;Decentralized Software Services&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="Concurrency and Coordination Runtime" href="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx"&gt;Concurrency and Coordination Runtime&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;" src="http://www.ajlopez.com/images/articles/roboticsraf.png" align="left" alt="" /&gt; Presentaré algunos de los ejemplos que había usado en el último Microsoft Regional Architect Forum, en base a la presentación de &lt;a href="http://www.thearchitectexchange.com/" target="_blank"&gt;Arvindra Sehmi&lt;/a&gt;, y otros ejemplos adicionales.&lt;/p&gt; &lt;p&gt;Todo sobre Microsoft Robotics Developer Studio, desde&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.microsoft.com/robotics"&gt;http://www.microsoft.com/robotics&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Concursos, desafíos, videos explicativos, desde el nuevo sitio de Robotics &lt;p&gt;&lt;a href="http://www.robochamps.com/"&gt;http://www.robochamps.com/&lt;/a&gt; &lt;p&gt;Enlaces que he coleccionado sobre estos temas en: &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/dss"&gt;http://del.icio.us/ajlopez/dss&lt;/a&gt; &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/ccr"&gt;http://del.icio.us/ajlopez/ccr&lt;/a&gt; &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/robotics"&gt;http://del.icio.us/ajlopez/robotics&lt;/a&gt; &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/msrs"&gt;http://del.icio.us/ajlopez/msrs&lt;/a&gt; &lt;p&gt;Nos leemos! &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1641369" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Rob_26002300_243_3B00_tica/default.aspx">Rob&amp;#243;tica</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Decentralized+Software+Services/default.aspx">Decentralized Software Services</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Microsoft+Robotics+Developer+Studio/default.aspx">Microsoft Robotics Developer Studio</category></item><item><title>Agentes Distribuidos y Fractales usando DSS/VPL</title><link>http://msmvps.com/blogs/lopez/archive/2008/06/23/agentes-distribuidos-y-fractales-usando-dss-vpl.aspx</link><pubDate>Mon, 23 Jun 2008 17:11:37 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1637058</guid><dc:creator>lopez</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1637058</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/06/23/agentes-distribuidos-y-fractales-usando-dss-vpl.aspx#comments</comments><description>&lt;p&gt;La semana pasada escribí una aplicación de base para agentes distribuidos usando DSS/VPL, agentes que intercambian mensajes arbitrarios e implementan un balanceo de carga rudimentario. Pueden leer los detalles en:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/06/20/agentes-distribuidos-usando-dss-vpl.aspx"&gt;Agentes Distribuidos usando DSS/VPL&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ajlopez.wordpress.com/2008/06/15/distributed-agents-using-dssvpl/"&gt;Distributed Agents using&amp;nbsp;DSS/VPL &lt;/a&gt;&lt;/p&gt; &lt;p&gt;Ayer, extendí el ejemplo con un nuevo proyecto, Fractal:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.todocontenidos.com/images/articles/fractalsln.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Pueden bajarlo desde &lt;a href="http://cid-9f903f3d6db0c176.skydrive.live.com/self.aspx/Examples/DSS/AjDssAgents-0.2.zip" target="_blank"&gt;mi Skydrive&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Tiene dos&amp;nbsp;DSS Service Components, uno es el&amp;nbsp;Calculator: calcula un sector del fractal de Mandelbrot. El otro componente es el Renderer, que tiene un formulario para controlar y mostrar los resultados del cálculo. El mensaje que transporta la información del sector a calcular es:&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:ed281842-4f1e-4878-87a4-5e9cc39d8478" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; SectorInfo : MessagePayload
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;double&lt;/span&gt;&lt;span style="color:#000000;"&gt; RealMinimum { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;double&lt;/span&gt;&lt;span style="color:#000000;"&gt; ImgMinimum { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;double&lt;/span&gt;&lt;span style="color:#000000;"&gt; Delta { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; FromX { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; FromY { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; Width { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; Height { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; MaxIterations { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; MaxValue { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Otra clase es el mensaje que retorna el cálculo:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:c23ce92b-efa1-4832-9743-2aeef1438dd2" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; Sector : MessagePayload
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; FromX { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; FromY { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; Width { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; Height { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt;[] Values { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;El Calculator divide el sector a calcular, si lo considera demasiado grade. Podría calcularlo en un solo paso, pero me parece interesante esta solución, para repartir el trabajo entre varios nodos:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:685af1f9-0d83-445f-89c6-e9b39667d0b9" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Calculate(AgentMessage msg)
        {
            LogInfo(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Entering Calculator with Action: &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;+&lt;/span&gt;&lt;span style="color:#000000;"&gt; msg.Action);
            SectorInfo sectorInfo &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; (SectorInfo) msg.Payload;
            LogInfo(String.Format(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;X {0} Y {1} Width {2} Height {3}&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, sectorInfo.FromX, sectorInfo.FromY, sectorInfo.Width, sectorInfo.Height));

            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (sectorInfo.Width &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;100&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color:#000000;"&gt; sectorInfo.Height &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;100&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
                SplitSector(sectorInfo);
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt;
                CalculateSector(sectorInfo);
        }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Como en el ejemplo de la semana pasada, podemos ejecutar este ejemplo desde un diagrama VPL, que se llama&amp;nbsp;FractalVpl1:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.todocontenidos.com/images/articles/fractalvpl1.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;Acá hay un solo Renderer, y dos agentes Calculator. Si lanzamos este programa VPL, aparece una ventana. Esta es su apariencia (luego de presionar el botón Calculate):&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.todocontenidos.com/images/articles/fractal2.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;Podemos arrastrar el mouse para seleccionar una nueva región, o usar los botones de Zoom In y Zoom Out. El botón de Reset vuelve a la posición y colores iniciales. El botón Reset Colors vuelve a los colores iniciales, que pueden ser cambiados al azar con el botón New Colors.&lt;/p&gt;
&lt;p align="left"&gt;Hay otro programa VPL, llamado&amp;nbsp;FractalVpl2, que puede ser usado para ejecutar el mismo ejemplo de forma distribuida. Tiene un diagrama con dos AgentHosts:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.todocontenidos.com/images/articles/fractalvpl2d.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;y dos nodos:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.todocontenidos.com/images/articles/fractalvpl2n.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;Debemos compilar el ejemplo VPL y pedir de ejecutar sus nodos en forma distribuida, usando el rundeployer.cmd (para más detalles, ver mi anterior post, mencionado al principio).&lt;/p&gt;
&lt;p align="left"&gt;Estos son algunos de los gráficos que produce el sistema:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.todocontenidos.com/images/articles/fractal1.png" alt="" /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.todocontenidos.com/images/articles/fractal4.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.todocontenidos.com/images/articles/fractal5.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;(Este post es una traducción del original en &amp;quot;Anglish&amp;quot;:&lt;/p&gt;
&lt;p align="left"&gt;&lt;a href="http://ajlopez.wordpress.com/2008/06/22/distributed-agents-and-fractals-using-dssvpl/"&gt;Distributed Agents and Fractals using&amp;nbsp;DSS/VPL &lt;/a&gt;&lt;/p&gt;
&lt;p align="left"&gt;)&lt;/p&gt;
&lt;p align="left"&gt;Nos leemos!&lt;/p&gt;
&lt;p align="left"&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;&lt;/p&gt;
&lt;p align="left"&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1637058" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Grid+Computing/default.aspx">Grid Computing</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Decentralized+Software+Services/default.aspx">Decentralized Software Services</category></item><item><title>Agentes Distribuidos usando DSS/VPL</title><link>http://msmvps.com/blogs/lopez/archive/2008/06/20/agentes-distribuidos-usando-dss-vpl.aspx</link><pubDate>Fri, 20 Jun 2008 10:44:33 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1636014</guid><dc:creator>lopez</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1636014</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/06/20/agentes-distribuidos-usando-dss-vpl.aspx#comments</comments><description>&lt;p&gt;En este post, exploraremos algunas ideas para implementar agentes distribuidos, aprovechando las capacidades&amp;nbsp;que nos brindan&amp;nbsp;Decentrilized Software Services (DSS) y el Visual Programming Language (VPL), includos en el &lt;a href="http://www.microsoft.com/robotics" target="_blank"&gt;Microsoft Robotics Developer Studio&lt;/a&gt; (estoy trabajando con la versión CTP 2.0, con VS 2008). Pueden bajarse el código desde mi Skydrive:&lt;/p&gt; &lt;p&gt;&lt;a href="http://cid-9f903f3d6db0c176.skydrive.live.com/self.aspx/Examples/DSS/AjDssAgents-0.1.zip" target="_blank"&gt;AjDssAgents-0.1.zip&lt;/a&gt;&lt;/p&gt; &lt;p&gt;En un anterior post:&lt;/p&gt; &lt;p&gt;&lt;a title="Web Crawler example using DSS (Decentralized Software Services)" href="http://ajlopez.wordpress.com/2008/05/25/web-crawler-example-using-dss-decentralized-software-services/"&gt;Web Crawler example using DSS (Decentralized Software Services)&lt;/a&gt;&lt;br /&gt;&lt;a title="Ejemplo de Web Crawler usando DSS (Decentralized Software Services)" href="http://msmvps.com/blogs/lopez/archive/2008/05/28/ejemplo-de-web-crawler-usando-dss-decentralized-software-services.aspx"&gt;Ejemplo de Web Crawler usando DSS (Decentralized Software Services)&lt;/a&gt;&lt;br /&gt;&lt;/p&gt; &lt;p&gt;escribí algunos componentes DSS orquestados desde VPL, para implementar un web crawler. En ese ejemplo, hay un Dispatcher, un Resolver, un Downloader, y un&amp;nbsp;Harvester. Pueden leer ahí el detalle de sus funciones.&lt;/p&gt; &lt;p&gt;Pero supongamos que ahora tenemos varias máquinas para poder ejecutar el proceso de web crawling. Queremos instalar y ejecutar varios Downloaders y Harvesters, en una grilla de máquinas, usando load balancing automático. El problema con la orquestación desde VPL es que no soporta conceptos como load balancing, por lo menos no directamente. Entonces, escribí este ejemplo donde los componentes se comunican entre sí, como agentes, usando mensajes especiales.&lt;/p&gt; &lt;p&gt;Un agente, en este ejemplo, es un DSS service component, capaz de recibir y procesar mensajes que les envían los otros agentes. Puede enviar mensajes a otros componentes. En vez de indicar a cuál agente va dirigido un mensaje, se especifica el tipo lógico de agente al que va destinado, por ejemplo &amp;quot;WebCrawler/Harvester&amp;quot;.&lt;/p&gt; &lt;p&gt;Otro componente especializado, el AgentHost, se encargar de recibir esos mensajes a enviar, y los destina a un agente local o remoto, que corresponda al tipo lógico especificado.&lt;/p&gt; &lt;h3&gt;La solución&lt;/h3&gt; &lt;p&gt;La solución .NET tiene tres proyectos:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajdssagentssln.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;AjDssAgents contiene el contrato genérico de un agente, y sus tipos, y la implementación concreta del AgentHost.&lt;/p&gt; &lt;p&gt;DecrementAgent and WebCrawler&amp;nbsp;son simples agentes a&amp;nbsp;usar en el ejemplo. El web crawler implementado es similar al&amp;nbsp;de mi anterior post, mencionado arriba.&lt;/p&gt; &lt;h3&gt;El mensaje&lt;/h3&gt; &lt;p&gt;Los agentes intercambian mensajes, objetos del tipo AgentMessage:&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:19c1260f-0edf-49ad-9ea5-ce3fd1a35bb3" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;
    [DataContract]
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; AgentMessage
    {
        [DataMember]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; From { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }

        [DataMember]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; To { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }

        [DataMember]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; Action { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }

        [DataMember]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; Payload { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;El campo From indica el origen del mensaje (no estoy usando ese campo todavía) El campo To es la dirección física (dirección DSSP) del agente destino, o su tipo lógico. En el ejemplo de este post, solamente estoy usando los tipos lógicos. ¿Por qué usar un tipo lógico? Así, si un mensaje tiene como To el valor &amp;quot;WebCrawler/Dispatcher&amp;quot;, será enviado a un agente que corresponda a ese tipo lógico.&lt;/p&gt;
&lt;p&gt;¿Cómo un agente conoce cuáles otros agentes están siendo ejecutados, y cuáles son sus tipos lógicos? Pues bien, no lo sabe. El componente que mantiene esa información es el AgenHost local, único en cada DssHost activo. Cada agente envía sus mensajes salientes a su AgentHost local, y éste los reenvía a los agentes locales o remotos apropiados.&lt;/p&gt;
&lt;h3&gt;Los agentes&lt;/h3&gt;
&lt;p&gt;Cada agente es un&amp;nbsp;DSS service component, con una dirección asignada cuando es creado. Durante el comienzo de su ejecucuón, el agente envía a su AgentHost local un mensaje DSS, indicando su dirección y su tipo lógico (p.ej. WebCrawler/Dispatcher). Esta es la forma por la que el AgentHost conoce los agentes que estan ejecutándose localmente, en su DssHost. Veamos el código de inicio de un agente Dispatcher del ejemplo WebCrawler:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:0f9d6b16-e418-434d-8269-c8c094c4e793" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;protected&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Start()
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;base&lt;/span&gt;&lt;span style="color:#000000;"&gt;.Start();
            &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt; Add service specific initialization here.&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;            _state.AgentType &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;WebCrawler/Dispatcher&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;;

            host.NewNode newNode &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; host.NewNode(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; host.AgentInfo() { Address &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.ServiceInfo.Service, AgentType &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _state.AgentType });
            _hostPort.Post(newNode);
        }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;El tipo del agente es mantenido en su estado.&lt;/p&gt;
&lt;p&gt;Este es un código típico, de un agente, en este caso un&amp;nbsp;Dispatcher, mostrando el tratamiento de un mensaje entrante y la producción de mensajes salientes:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:43d1f629-7d87-47b8-960c-1fc30002b3c2" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;        [ServiceHandler(ServiceHandlerBehavior.Concurrent)]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; IEnumerator&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;ITask&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; PostMessageHandler(generic.PostMessage postMessage)
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (postMessage.Body.Action.Equals(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Dispatch&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;))
                Dispatch(postMessage.Body);
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (postMessage.Body.Action.Equals(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Resolve&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;))
                Resolve(postMessage.Body);

            postMessage.ResponsePort.Post(DefaultSubmitResponseType.Instance);

            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;yield&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;break&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
        }

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Dispatch(AgentMessage msg)
        {
            LogInfo(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Entering Dispatcher with Action: &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;+&lt;/span&gt;&lt;span style="color:#000000;"&gt; msg.Action);
            LogInfo(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;URL: &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;+&lt;/span&gt;&lt;span style="color:#000000;"&gt; msg.Payload);

            DownloadTarget target &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; DownloadTarget();

            target.Uri &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt;) msg.Payload;
            target.Depth &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;1&lt;/span&gt;&lt;span style="color:#000000;"&gt;;

            AgentMessage postmsg &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; AgentMessage() { Action &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Resolve&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, To &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; _state.AgentType, Payload &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; target };
            host.PostMessage post &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; host.PostMessage(postmsg);
            _hostPort.Post(post);
        }

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Resolve(AgentMessage msg)
        {
            LogInfo(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Entering Dispatcher with Action: &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;+&lt;/span&gt;&lt;span style="color:#000000;"&gt; msg.Action);
            DownloadTarget downloadtarget &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; (DownloadTarget)msg.Payload;

            LogInfo(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;URL: &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;+&lt;/span&gt;&lt;span style="color:#000000;"&gt; downloadtarget.Uri &lt;/span&gt;&lt;span style="color:#000000;"&gt;+&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Depth: &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;+&lt;/span&gt;&lt;span style="color:#000000;"&gt; downloadtarget.Depth);

            DownloadTarget target &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessUrl(downloadtarget);

            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (target &lt;/span&gt;&lt;span style="color:#000000;"&gt;!=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;) {
                AgentMessage agentmsg &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; AgentMessage() { To &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;WebCrawler/Downloader&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Action&lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Download&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Payload &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; downloadtarget };
                host.PostMessage postmsg &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; host.PostMessage(agentmsg);
                _hostPort.Post(postmsg);
            }
        }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;El AgentHost&lt;/h3&gt;
&lt;p&gt;Hay uno y sólo uno por DssHost en ejecución. El AgentHost recibe la información de los nuevos agentes que se crean (su dirección y tipo lógico), y mantiene esa información en su propio estado.&lt;/p&gt;
&lt;p&gt;Recibe mensajes de sus agentes locales, y los reenvía a otros agentes locales o a un AgentHost remoto. En este último caso, serializa el contenido del mensaje en un string, usando serialización XML (no podemos enviar un objeto genérico, debido a limitaciones en el Proxy que usa DSS). Esta es la estructura de un mensaje remoto:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:a9815df5-5156-48a3-ba52-7c6468e48c46" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    [DataContract]
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; RemoteAgentMessage
    {
        [DataMember]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; From { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }

        [DataMember]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; To { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }

        [DataMember]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; Action { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }

        [DataMember]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; PayloadTypeName { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }

        [DataMember]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; Payload { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;; }
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Notemos que el mensaje remote tiene un string Payload, que es la serialización XML del&amp;nbsp;contenido original, y también tiene su tipo calificado, así el host destino podrá deserializarlo&amp;nbsp;a su tipo correspondiente al objeto original.&lt;/p&gt;
&lt;p&gt;Un AgentHost soporta subscripciones. Otros AgentHosts pueden subscribirse a recibir información de sus nuevos agentes. En general, si tenemos tres máquinas, debemos susbcribir a los tres AgentHosts entre ellos, así tendrán toda la información de los agentes que se encuentre corriendo, en las distintas máquinas.&lt;/p&gt;
&lt;h3&gt;Un ejemplo de Web Crawler con VPL&lt;/h3&gt;
&lt;p&gt;El ejemplo&amp;nbsp;WebCrawlerVpl2 en VPL contiene dos diagramas, el primero:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajdssagentsvpldiag.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Hay un Dispatcher, dos Downloaders y dos agentes&amp;nbsp;Harvesters. El Dispatcher lanza la URL inicial a procesar, y mantiene una lista de URLs ya procesadas. El Downloader obtiene el contenido de cada página en proceso. El Harvester examina el contenido y obtiene los nuevos links a procesar.&lt;/p&gt;
&lt;p&gt;Notemos que hay dos&amp;nbsp;AgentHosts, y&amp;nbsp;ellos se relacionan&amp;nbsp;por notificaciones para informar sus nuevos agentes al otro.&lt;/p&gt;
&lt;p&gt;Todos estos agentes y componentes se distribuyen en dos nodos:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajdssagentsvplnodes.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;El nodo Windows ejecutará en localhost:50000/50001, y el nodo&amp;nbsp;Windows0 usar localhost:50002/50003 como dirección. Podemos modificar estos parámetros, agregar más agentes y nodos, sin cambiar el código de la aplicación.&lt;/p&gt;
&lt;p&gt;Para ejecutar la distribución en forma distribuida, debemos compilarlar usando &lt;strong&gt;Build -&amp;gt; Compile as a Service&lt;/strong&gt; en el menú de VPL. Deberá cambiar las propiedades de VPL, ahora en el ejemplo están apuntando a directorios locales en mi máquina de desarrollo:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dsslispvpl0.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Al compilar, VPL mostrará su avance:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajdssagentscompile.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Luego de la compilación, ir a la consola de DOS de MRDS, cambiar al directorio bin y lanzar el comando rundeployer.cmd:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajdssagentsrundpl.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;Yo ejecuto el deployer en mi máquina local. Uds. pueden ejecutar el ejemplo en otras máquinas remotas, iniciando el deployer en cada una de ellas.&lt;/p&gt;
&lt;p align="left"&gt;Ahora, estamos listos para ejecutar el&amp;nbsp;web crawler. Seleccionamos&amp;nbsp;la opción&amp;nbsp;&lt;strong&gt;Run -&amp;gt; Run on distributed nodes&lt;/strong&gt; , y la aplicación comenzará a ejecutar. Un ventana de diálogo nos pedirár la URL inicial. La ingresamos, y el proceso comienza a recuperar las páginas de ese sitio. Pueden ver el estado del primer AgentHost (ejemplo) en:&lt;/p&gt;
&lt;p align="left"&gt;&lt;a href="http://localhost:50000/agenthost"&gt;http://localhost:50000/agenthost&lt;/a&gt;&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajdssagents50000.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;Hay tres agentes locales y dos agentes remotos.&lt;/p&gt;
&lt;p align="left"&gt;En el otro DssHost, hay otro&amp;nbsp;AgentHost:&lt;/p&gt;
&lt;p align="left"&gt;&lt;a href="http://localhost:50002/agenthost0"&gt;http://localhost:50002/agenthost0&lt;/a&gt;&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajdssagents50002.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;Vemos la diferencia: aquí hay dos nodos locales y tres remotos.&lt;/p&gt;
&lt;p align="left"&gt;Para ver el avance del proceso, pedir en el navegador&lt;/p&gt;
&lt;p align="left"&gt;&lt;a href="http://localhost:50000/console/output"&gt;http://localhost:50000/console/output&lt;/a&gt;&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajdssagentscon1.png" alt="" /&gt; &lt;/p&gt;
&lt;h3&gt;Conclusiones&lt;/h3&gt;
&lt;p&gt;Con estas ideas, podemos implementar aplicaciones tipo grilla, ejecutándose en varios nodos físicos. Perdemos la orquestación de VPL, no podemos dibujar el camino de los mensajes. Pero ganamos en balanceo de carga y deploying dinámico. Con algo de esfuerzo adicional, podemos escribir un servicio que inicia e instale el sistema en una nueva máquina remota, en el medio de un proceso en ejecución. La serialización de objetos arbitrarios es posible, ahora está usando serialización XML, podemos cambiarla por serialización &amp;quot;custom&amp;quot; o binaria.&lt;/p&gt;
&lt;p&gt;Podría agregar subscripción a mensajes, en una futura versión. Un agente podría recibir mensajes que no estaban destinados a él, especificando algún criterio de subscripción. Esos criterios se mantendrían en los AgentHosts. Cuando un AgentHost rutea un mensaje saliente, podría reenviar una copia del mismo a cualquier agente interesando, ya sea local o remoto.&lt;/p&gt;
&lt;p&gt;Tienen la versión original de este post en &amp;quot;Anglish&amp;quot;:&lt;/p&gt;
&lt;p&gt;&lt;a title="http://ajlopez.wordpress.com/2008/06/15/distributed-agents-using-dssvpl" href="http://ajlopez.wordpress.com/2008/06/15/distributed-agents-using-dssvpl"&gt;http://ajlopez.wordpress.com/2008/06/15/distributed-agents-using-dssvpl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/en"&gt;http://www.ajlopez.com/en&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1636014" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Grid+Computing/default.aspx">Grid Computing</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Decentralized+Software+Services/default.aspx">Decentralized Software Services</category></item><item><title>Intérprete tipo Lisp usando DSS y VPL</title><link>http://msmvps.com/blogs/lopez/archive/2008/06/11/int-233-rprete-tipo-lisp-usando-dss-y-vpl.aspx</link><pubDate>Wed, 11 Jun 2008 14:22:24 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1634011</guid><dc:creator>lopez</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1634011</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/06/11/int-233-rprete-tipo-lisp-usando-dss-y-vpl.aspx#comments</comments><description>&lt;p&gt;Este fin de semana estuve programando algunas primitivas de un intérprete Lisp usando DSS Service Compoenntes. El núcleo del intérprete fue derivado de mi trabajo previo con AjLisp, un intérprete que todavía no publiqué. Escribí el ejemplo usando Visual Studio 2008 con el CTP v2.0 de &lt;a href="http://www.microsoft.com/robotics" target="_blank"&gt;Microsoft Robotics Developer Studio&lt;/a&gt;. El ejemplo está publicado en mi Skydrive como &lt;a href="http://cid-9f903f3d6db0c176.skydrive.live.com/self.aspx/Examples/DSS/DssLisp.zip" target="_blank"&gt;DssLisp.zip&lt;/a&gt;.&lt;/p&gt; &lt;h3&gt;La solución&lt;/h3&gt; &lt;p&gt;Consiste de dos proyectos: una librería de clases llamada&amp;nbsp;AjLisp (una versión revisada de mi intérprete original en VB.NET):&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dsslispajlisp.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;y un proyecto C# de Dss Service, que tiene varios service components implementados:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dsslispdss.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;No tiene manifiesto inicial. El proyecto está pensado para ser usado desde diagramas de Visual Programming Language (VPL).&lt;/p&gt; &lt;p&gt;Varios de estos componentes reciben y retornan una SymbolicExpression, el tipo base de mi intérprete. Veamos por ejemplo, los mensajes del componente Rest, que dada una lista devuelve la misma lista sin el primer elemento:&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:1618d506-618e-4139-9950-8639333a6fc3" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    [DataContract()]
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; ExecuteRequest
    {
        [DataMember]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; SymbolicExpression Expression;
    }

    [DataContract]
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; ExecuteResponse
    {
        [DataMember]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; SymbolicExpression Result;
    }
    
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para compilar estos componentes, deben ajustar las referencias y directorios del proyecto DSS (ahora apuntan a mis directorios locales y a mi instalación local de Microsoft Robotics Developer Studio).&lt;/p&gt;
&lt;h3&gt;Usando VPL&lt;/h3&gt;
&lt;p&gt;Hay tres programas VPL incluidso en los ejemplos. Usan los componentes compilados de la solución. Tuve un problema con estos programas VPL. No pude ejecutarlos desde la opción de&amp;nbsp; &lt;strong&gt;Run&lt;/strong&gt;. Hay que usar &lt;strong&gt;Build -&amp;gt; Compile as a Service&lt;/strong&gt;, y ahora, lanzarlos con &lt;strong&gt;Run -&amp;gt; Run Compiled Services&lt;/strong&gt;. Creo que el origen del problema es que al armar el diagrama estoy mapeando mensajes propios, no solamente tipos primitivos o Strings. Para recompilar los diagramas, tienen que ajustar las propiedades en cada proyecto VPL:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dsslispvpl0.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;El primero,&amp;nbsp; &lt;strong&gt;DssLispVpl1,&amp;nbsp;&lt;/strong&gt;calcula (first &amp;#39;(a b c)):&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dsslispvpl1.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="center"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align="left"&gt;Hay dos componentes LispParser y LispToString, que ayudan a convertir de string a SymbolicExpression y viceversa.&lt;/p&gt;
&lt;p align="left"&gt;El segundo diagrama es &lt;strong&gt;DssLispVpl2&lt;/strong&gt;:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dsslispvpl2.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;Usa el componente LispAppend para concatenar dos listas predefinidas como Data.&lt;/p&gt;
&lt;p align="left"&gt;El tercero es un min intérprete &lt;strong&gt;DsspLispInterpreter&lt;/strong&gt;:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dsslispvpl3.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Tengo que mejorar el tratamiento de errores. Ahora, si ocurre una excepción, no devuelve un Fault, y encontes se genera una causality, que hace que el programa se interrumpa.&lt;/p&gt;
&lt;p&gt;Podría implementar contratos genéricos, y reusarlos en los componentes, por ejemplo, un contrato GenericBinaryOperation.&lt;/p&gt;
&lt;h3&gt;Problemas&lt;/h3&gt;
&lt;p align="left"&gt;Fallé completamente cuando quise escribir una Activity, para implementar una función Reverse de una lista. La actividad se llamaba a sí misma recursivamente, pero en el código generador retornaba desde la última invocación recursiva, sin pasar por las intermedias. El problema es causado porque en todo ese proceso se utiliza la misma instancia de actividad, y al retornar por una puerta el resultado, TODOS los procesos pendientes de esa actividad están escuchando por esa puerta (eso es lo que veo que pasa). Otra piedra en el camino es que las actividades solo aceptan valores primitivos o string como datos en el mensaje de entrada. Puedo solucionar el problema, generando el código de la actividad, levantando la solución, y cambiando los parámetros que trata de, digamos, string a SymbolicExpression.&lt;/p&gt;
&lt;p align="left"&gt;Un componente interesante, es el componente Uncons, que retorna DOS expresiones simbólicas en su mensaje de respuesta: dada una lista, retorna su cabeza y su cola. Esos dos miembros de la respuesta pueden ser procesados luego en paralelo en dos ramas del diagrama.&lt;/p&gt;
&lt;h3&gt;Conclusiones&lt;/h3&gt;
&lt;p align="left"&gt;Como en otros posts y ejemplos, encontré la orquestación de componentes DSS via VPL como algo poderoso e interesante, pero le faltan algunas cosas, como el soporte de un objeto genérico o tipos&amp;nbsp;nuestros. Creo que se puede implementar varias primitivas de lenguajes funcionales y usar a VPL para programar sobre ellas. VPL tendría problemas con la recursividad (o no encontré una forma aceptable de hacerla funcionar). Este ejercicio,&amp;nbsp;podría expandirse a otras ideas:&lt;/p&gt;
&lt;p align="left"&gt;- Manejar una pipeline/tubería para procesar un mensaje genérico (puedo usar un object como DataMember en un mensaje, siempre y cuando no lo envía a otro Host de DSS)&lt;br /&gt;- Tener balanceo de carga&lt;br /&gt;- Serializar/deserializar objetos entre hosts&lt;br /&gt;- Implementar algún workflow o patrones de integración de aplicaciones usando VPL&lt;/p&gt;
&lt;p align="left"&gt;Nos leemos!&lt;/p&gt;
&lt;p align="left"&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;&lt;/p&gt;
&lt;p align="left"&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1634011" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Decentralized+Software+Services/default.aspx">Decentralized Software Services</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category></item><item><title>Ejemplo de Web Crawler usando DSS (Decentralized Software Services)</title><link>http://msmvps.com/blogs/lopez/archive/2008/05/28/ejemplo-de-web-crawler-usando-dss-decentralized-software-services.aspx</link><pubDate>Wed, 28 May 2008 18:18:54 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1628395</guid><dc:creator>lopez</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1628395</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/05/28/ejemplo-de-web-crawler-usando-dss-decentralized-software-services.aspx#comments</comments><description>&lt;p&gt;Hace unas semanas,&amp;nbsp;escribí una aplicación tipo Scribble distribuido usando DSS.&amp;nbsp;A fin de la semana pasada, escribí otra aplicación, para aprender conceptos de DSS: una aplicación que visita y baja&amp;nbsp;páginas web de un sitio,&amp;nbsp;con&amp;nbsp;servicios DSS&amp;nbsp;coordinados desde&amp;nbsp;Visual Programming Language (VPL). Hay un programa VPL adicional que lee una página web, usando un control Texto to Speech. Pueden bajarse el ejemplo desde mis carpetas en Skydrive:&lt;/p&gt; &lt;p&gt;&lt;a href="http://cid-9f903f3d6db0c176.skydrive.live.com/self.aspx/Examples/DSS/DssWebCrawler2008May.zip" target="_blank"&gt;DssWebCrawler2008May.zip&lt;/a&gt;&lt;/p&gt;&lt;iframe style="border-right:#dde5e9 1px solid;padding-right:0px;border-top:#dde5e9 1px solid;padding-left:0px;padding-bottom:0px;margin:3px;border-left:#dde5e9 1px solid;width:240px;padding-top:0px;border-bottom:#dde5e9 1px solid;height:66px;background-color:#ffffff;" src="http://cid-9f903f3d6db0c176.skydrive.live.com/embedrowdetail.aspx/Examples/DSS/DssWebCrawler2008May.zip" frameborder="0" scrolling="no"&gt;&lt;/iframe&gt; &lt;h3&gt;La solución&lt;/h3&gt; &lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;" src="http://www.ajlopez.com/images/articles/dsswebcrawler.png" align="left" alt="" /&gt;&amp;nbsp;Está compuesta de tres proyectos: un assembly DSS, uno de librería de clases con algunos utilitarios para analizar contenido HTML, y una librería de clases para hacer testint del parser HTML. La librería de test usa NUnint: pueden removerla de la solución, si quieren, porque sólo es usada para testing, no para la solución final.&lt;/p&gt; &lt;p&gt;El assembly que usa DSS assembly se llama DssWebCrawler. Definí ahí 5&amp;nbsp;servicios DSS:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Dispatcher&lt;/strong&gt;: Recibe una URL inicial para bajar, y la envía al Resolver.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Resolver&lt;/strong&gt;: Este servicio mantiene una lista de URLs visitadas, y controla si las nuevas URLs a bajar son válidas, que pertenezcan al mismo dominio, y que no hayan sido ya procesadas. Está limitado por código a explorar hasta 3 niveles de enlaces.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Downloader&lt;/strong&gt;: Este servicio lee el contenido de una URL. El contenido obtenido es parte del mensaje de respuesta.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Harvester&lt;/strong&gt;: Examina el contenido recibido y recolecta nuevas URLs de los enlaces que encuentra dentro. Para cada uno de esos enlaces, envía una notificación a cualquier servicio interesado en esa información.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Reader&lt;/strong&gt;: Usa el simple parser HTML que escribí para el proyecto. Puede obtener el título de una página, o el contenido, descartando tags de HTML y scripts.&lt;/p&gt; &lt;h3&gt;The VPL Program&lt;/h3&gt; &lt;p&gt;Hay un program VPL (Visual Programming Language), llamado VPLWebCrawler. Consiste en tres diagramas. El primero define el envío de la primer URL a bajar:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/vplwebcrawler1.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;El segundo define el proceso de notificación de nuevas URLs encontradas por el componente Harvester:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/vplwebcrawler2.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;El tercer diagrama es un &amp;quot;plus&amp;quot;: procesa las notificaciones del Downloader, informando nuevo contenido, lo examina, y envía el título de la página bajada a un componente Text to Speech:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/vplwebcrawler3.png" alt="" /&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Para lanzar la aplicación, ir al menú &lt;strong&gt;Run -&amp;gt; Start&lt;/strong&gt; . Aparece una ventana, pidiendo de ingresar la URL de la página para comenzar a &amp;quot;crawlear&amp;quot;:  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/vplwebreaderprompt.png" alt="" /&gt;  &lt;p&gt;Comienza el proceso de &amp;quot;crawling&amp;quot;:  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/vplwebreaderrun.png" alt="" /&gt;  &lt;p&gt;Despues de algunos segundos, los títulos de las páginas bajadas son enviados al servicio Texto to Speech: escucharemos el proceso de cada página.  &lt;h3&gt;Leyendo páginas&lt;/h3&gt; &lt;p&gt;En otro programa VPL, el&amp;nbsp;VPLWebReader, podemos leer &amp;quot;en voz alta&amp;quot; el contenido de una página web, usando el componente Text to Speech:  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/vplwebreader.png" alt="" /&gt;  &lt;p&gt;Es interesante ver que estamos usando los mismos componentes que en el anterior ejemplo. Pero usando composición VPL, podemos usarlos para otros programas.  &lt;p&gt;Pueden usarlo para leer mis experimentos en &amp;quot;Anglish&amp;quot; (Angel&amp;#39;s English) apuntando a &lt;a href="http://ajlopezen.zoomblog.com"&gt;http://ajlopezen.zoomblog.com&lt;/a&gt;.  &lt;h3&gt;Conclusiones&lt;/h3&gt; &lt;p&gt;Los componentes fueron escritos para ser usados desde orquestración de VPL. No tienen &amp;quot;partners&amp;quot;, ni conexiones directas entre ellos. Esta es ua nueva manera de programar: definimos nuestros mensajes de entrada y de respuesta, y luego los usamos desde VPL. La posibilidad de usar notificaciones es algo interesante: se puede usar para usar la misma salida en diferentes componentes destinos.  &lt;p&gt;Podemos jugar un poco más: pruebe de colocar algunos de estos componentes en otro nodo/máquina, usando las nuevas capacidades de &amp;quot;deployer&amp;quot; automático desde VPL.  &lt;p&gt;Espero que encuentren este ejemplo útil: me divertí escribiéndolo, hay más aplicaciones que quisiera pasar a código usando estas tecnologías.  &lt;p&gt;Gracias a&amp;nbsp;Fernando Tubio, por sus ideas iniciales para implementar un web crawler.  &lt;p&gt;Nos leemos! &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1628395" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Decentralized+Software+Services/default.aspx">Decentralized Software Services</category></item><item><title>Presentando Microsoft Robotics en el Regional Architect Forum 2008</title><link>http://msmvps.com/blogs/lopez/archive/2008/05/27/presentando-microsoft-robotics-en-el-regional-architect-forum-2008.aspx</link><pubDate>Tue, 27 May 2008 07:42:56 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1627764</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1627764</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/05/27/presentando-microsoft-robotics-en-el-regional-architect-forum-2008.aspx#comments</comments><description>&lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;" src="http://www.ajlopez.com/images/articles/roboticsraf.png" align="left" alt="" /&gt; Hoy voy a presentar en el RAF 2008 del Cono Sur, en Pilar, Buenos Aires, conceptos y demos de Microsoft Robotics Developer Studio. Como la semana pasada, voy a usar como base una versión reducida de la presentación de &lt;a href="http://blogs.msdn.com/asehmi/" target="_blank"&gt;Arvindra Sehmi&lt;/a&gt;:&lt;/p&gt; &lt;p&gt;&lt;a title="A Data-Driven Approach to Distributed, Concurrent Software - ASEHMI - April 2008.pptx" href="http://cid-a5f7ad2e511a1926.skydrive.live.com/self.aspx/Public/A%20Data-Driven%20Approach%20to%20Distributed,%20Concurrent%20Software%20-%20ASEHMI%20-%20April%202008.pptx"&gt;A Data-Driven Approach to Distributed, Concurrent Software - ASEHMI - April 2008.pptx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Esta vez, la charla estará más centrada en las capacidades de armar aplicaciones distribuidas, y analizar el modelo de servicios que ofrece. Es un poco difícil explicar algunos de los conceptos claves sólo en 50 minutos, pero espero que pueda marcar que estas herramientas son para más allá de robótica.&lt;/p&gt; &lt;p&gt;Para más información sobre Microsoft Robotics, visitar:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.microsoft.com/robotics"&gt;http://www.microsoft.com/robotics&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Ejemplos presentados por Arvindra Sehmi en su &lt;a href="http://blogs.msdn.com/asehmi/archive/2008/05/03/mexico-regional-architect-forum-2008.aspx" target="_blank"&gt;RAF México&lt;/a&gt;:&lt;/p&gt; &lt;p&gt;&lt;a title="CCRBasics.rar" href="http://9bqnjw.bay.livefilestore.com/y1pmUI3Zsybp13NI_WJ9P_7JpReGxOwgYIWb44YWHCwEphOXm6VKpOdGvMdNG5s466iuZxEOivBmmmBjr9h7uiHYw/CCRBasics.rar?download"&gt;CCRBasics.rar&lt;/a&gt;&lt;/p&gt; &lt;p&gt;En estos días escribí un ejemplo de uso de DSS, para implementar un Web Crawler:&lt;/p&gt; &lt;p&gt;&lt;a title="Web Crawler example using DSS (Decentralized Software Services)" href="http://ajlopez.wordpress.com/2008/05/25/web-crawler-example-using-dss-decentralized-software-services/"&gt;Web Crawler example using DSS (Decentralized Software Services)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Ya vendrá el post correspondiente en español.&lt;/p&gt; &lt;p&gt;Un ejemplo anterior:&lt;/p&gt; &lt;p&gt;&lt;a title="Distributed Scribble with Microsoft Robotics Developer Studio and DSS" href="http://ajlopez.wordpress.com/2008/04/20/distributed-scribble-with-microsoft-robotics-developer-studio-and-dss/"&gt;Distributed Scribble with Microsoft Robotics Developer Studio and DSS&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Varios de los ejemplos que presento, están incluidos en el propio producto. El año pasado estuve implementando &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjMessages/default.aspx" target="_blank"&gt;AjMessages&lt;/a&gt; usando DSS/CCR, pero todavía no tengo algo publicado. Para un cliente, estoy desarrollando una aplicación distribuida, configurable, usando todas estas tecnologías, espero que quede publicada, para poder bloguear sobre el tema.&lt;/p&gt; &lt;p&gt;Para una detallada explicación de CCR, leer:&lt;/p&gt; &lt;p&gt;&lt;a title="MSDN Mag - Concurrent Affairs - Concurrency and Coordination Runtime" href="http://msdn.microsoft.com/en-gb/magazine/cc163556.aspx"&gt;MSDN Mag - Concurrent Affairs - Concurrency and Coordination Runtime&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Concursos, desafíos, videos explicativos, desde el nuevo sitio&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.robochamps.com/"&gt;http://www.robochamps.com/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;He dejado enlaces sobre estos temas en:&lt;/p&gt; &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/dss"&gt;http://del.icio.us/ajlopez/dss&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/ccr"&gt;http://del.icio.us/ajlopez/ccr&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/robotics"&gt;http://del.icio.us/ajlopez/robotics&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/msrs"&gt;http://del.icio.us/ajlopez/msrs&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Nos leemos!&lt;/p&gt; &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1627764" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Rob_26002300_243_3B00_tica/default.aspx">Rob&amp;#243;tica</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Microsoft+Robotics+Developer+Studio/default.aspx">Microsoft Robotics Developer Studio</category></item><item><title>Presentando Microsoft Robotics Developer Studio</title><link>http://msmvps.com/blogs/lopez/archive/2008/05/21/presentando-microsoft-robotics-developer-studio.aspx</link><pubDate>Wed, 21 May 2008 03:54:30 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1625386</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1625386</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/05/21/presentando-microsoft-robotics-developer-studio.aspx#comments</comments><description>&lt;p&gt;Hoy voy a estar presentando esta tecnología en la Universidad Tecnológica Nacional, de La Plata, provincia de Buenos Aires. Página base en:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.microsoft.com/robotics"&gt;http://www.microsoft.com/robotics&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Es una de las conferencias del&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.frlp.utn.edu.ar/web/ceneisi/home.html" target="_blank"&gt;Congreso Nacional de Estudiantes de Ingeniería en Sistemas de Información&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Mi conferencia es&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.frlp.utn.edu.ar/web/ceneisi/microsoft_robotic.html" target="_blank"&gt;Microsoft Robotics Studio&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Uso una versión resumida de la&amp;nbsp;presentación del bueno de &lt;a href="http://blogs.msdn.com/asehmi/" target="_blank"&gt;Arvindra Sehmi&lt;/a&gt;, que pueden bajar completa de:&lt;/p&gt; &lt;h6&gt;&lt;a href="http://cid-a5f7ad2e511a1926.skydrive.live.com/self.aspx/Public/A%20Data-Driven%20Approach%20to%20Distributed,%20Concurrent%20Software%20-%20ASEHMI%20-%20April%202008.pptx"&gt;&lt;font face="Arial" size="2"&gt;A Data-Driven Approach to Distributed, Concurrent Software - ASEHMI - April 2008.pptx&lt;/font&gt;&lt;/a&gt;&lt;/h6&gt; &lt;p&gt;La idea es mostrar, en dos horas, las ideas principales en las que se basa:&lt;/p&gt; &lt;p&gt;- Decentralized Software Services&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/roboticsdss.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;- Concurrent and Coordination Runtime&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/roboticsccr.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;- Visual Programming Language&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/roboticsvpl.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;- Simulation Environment&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/roboticssim2.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;- Robots simulados&lt;/p&gt; &lt;p&gt;- Soporte de la industria&lt;/p&gt; &lt;p&gt;Es muy fácil de instalar, y la última versión funciona y se maneja desde Visual Studio 2005 o 2008.&lt;/p&gt; &lt;p&gt;Más información sobre estas tecnologías en&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.robochamps.com"&gt;http://www.robochamps.com&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/robotics"&gt;http://del.icio.us/ajlopez/robotics&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/dss"&gt;http://del.icio.us/ajlopez/dss&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/ccr"&gt;http://del.icio.us/ajlopez/ccr&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Tengo algunos ejemplos a publicar, con CCR y DSS. Ya vieron algunos en:&lt;/p&gt; &lt;p&gt;&lt;a title="Genetic Algorithms with AjAgents and Concurrency and Coordination Runtime (CCR)" href="http://ajlopez.wordpress.com/2008/04/10/genetic-algorithms-with-ajagents-and-concurrency-and-coordination-runtime-ccr/"&gt;Genetic Algorithms with AjAgents and Concurrency and Coordination Runtime (CCR)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="Distributed Scribble with Microsoft Robotics Developer Studio and DSS" href="http://ajlopez.wordpress.com/2008/04/20/distributed-scribble-with-microsoft-robotics-developer-studio-and-dss/"&gt;Distributed Scribble with Microsoft Robotics Developer Studio and DSS&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="Agents using Concurrency and Coordination Runtime (CCR)" href="http://ajlopez.wordpress.com/2007/10/17/agents-using-concurrency-and-coordination-runtime-ccr/"&gt;Agents using Concurrency and Coordination Runtime (CCR)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Artículo introductorio a CCR en&lt;/p&gt; &lt;p&gt;&lt;a title="Concurrent Affairs- Concurrency and Coordination Runtime" href="http://msdn.microsoft.com/msdnmag/issues/06/09/ConcurrentAffairs/default.aspx"&gt;Concurrent Affairs- Concurrency and Coordination Runtime&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Espero repetir esta charla en otros lugares, como el MUG de Argentina o el Club de Programadores. La semana que viene doy una charla sobre el mismo tema, pero más orientada a aplicaciones distribuidas, en el Regional Architect Forum 2008 de Cono Sur. Algo más sobre grid computing en varios artículos:&lt;/p&gt; &lt;p&gt;&lt;a title="http://msmvps.com/blogs/lopez/archive/tags/Grid+Computing/default.aspx" href="http://msmvps.com/blogs/lopez/archive/tags/Grid+Computing/default.aspx"&gt;http://msmvps.com/blogs/lopez/archive/tags/Grid+Computing/default.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Todo lo de Microsoft Robotics Developer Studio se puede aplicar para eso.&lt;/p&gt; &lt;p&gt;Nos leemos!&lt;/p&gt; &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1625386" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Rob_26002300_243_3B00_tica/default.aspx">Rob&amp;#243;tica</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Microsoft+Robotics+Developer+Studio/default.aspx">Microsoft Robotics Developer Studio</category></item><item><title>Scribble Distribuido con Microsoft Robotics Developer Studio y DSS</title><link>http://msmvps.com/blogs/lopez/archive/2008/04/28/scribble-distribuido-con-microsoft-robotics-developer-studio-y-dss.aspx</link><pubDate>Mon, 28 Apr 2008 09:58:51 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1607097</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1607097</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/04/28/scribble-distribuido-con-microsoft-robotics-developer-studio-y-dss.aspx#comments</comments><description>&lt;p&gt;Estuve jugando con el nuevo CTP release de Microsoft Robotics Developer Studio. Tiene nuevas características, como instalación y ejecución de un diagrama de Visual Programming Language en muchos nodos.&lt;/p&gt; &lt;p&gt;Para explorar algo de esta nueva funcionalidad, escribí el sueño de todo programador: un programa de dibujo distribuido multiusuario...;-)... Bueno, es uno bastante simple, pero funciona, y puede ejecutarse en varias máquinas, exponiendo y compartiendo nuestros más inspirados dibujos de mouse. El código puede ser descargado desde &lt;a href="http://www.ajlopez.com/downloads/DssScribble.zip"&gt;aquí&lt;/a&gt;.&lt;/p&gt; &lt;h3&gt;El proyecto&lt;/h3&gt; &lt;p&gt;Tengo la versión 1.5 del MSRS y el nuevo CTP MRDS (nueva sigla), ejecutándose en la misma máquina, sin mayores problemas. Comencé creando un nuevo proyecto del tipo Simple Dss Service RDS 2008:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dssscribprj.png" alt="" /&gt; &lt;/p&gt; &lt;p align="left"&gt;El proyecto contiene un service component llamado DssScribble, y un&amp;nbsp;Windows form, que está a cargo del dibujo:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dssscribsln.png" alt="" /&gt; &lt;/p&gt; &lt;p align="left"&gt;Al comienzo del service component, crea el formulario, y lo connecta para usar los ports y su cola de dispatcher:&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:be5c684c-2d45-4b54-8900-6139c92c1a63" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;protected&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Start()
{
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;base&lt;/span&gt;&lt;span style="color:#000000;"&gt;.Start();
    &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt; Add service specific initialization here.&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;   WinFormsServicePort.Post(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; RunForm(CreateForm));
}

&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; Form CreateForm()
{
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; CanvasForm(_mainPort, linePort, TaskQueue);
}
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Cada línea que el usuario dibuja en la ventana es enviada al service component, para ser distribuido a cada subscriptor interesado en el dato:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:9c1e3690-1e0e-4f8a-a7fd-11cc3954d16e" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;[ServiceHandler(ServiceHandlerBehavior.Exclusive)]
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; IEnumerator&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;ITask&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; PostLineHandler(PostLine postLine)
{
    SendNotification&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;PostLine&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(_submgrPort, postLine);

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;yield&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;break&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
}
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Las líneas son recibidas en el NewLineHandler (el modo de conectar dos componentes es via VPL, como veremos más adelante). El linePort es el port para comunicarse con la instancia del formulario:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:2b7373d7-6830-4789-84c6-435af48c8805" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;[ServiceHandler(ServiceHandlerBehavior.Exclusive)]
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; IEnumerator&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;ITask&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; NewLineHandler(NewLine newLine)
{
    linePort.Post(newLine.Body);

    newLine.ResponsePort.Post(DefaultUpdateResponseType.Instance);

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;yield&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;break&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
}
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;El service component no tiene estado. Uso una clase para transportar la información de las nuevas líneas a dibujar y distribuir:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:4ba65ae9-4694-4a58-b156-5cb25864e3fe" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;width:398px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    [DataContract()]
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; DssScribbleState
    {
    }

    [DataContract()]
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; DssScribbleLine
    {
        [DataMember()]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; fromX;

        [DataMember()]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; fromY;

        [DataMember()]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; toX;

        [DataMember()]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; toY;

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; DssScribbleLine()
        {
        }

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; DssScribbleLine(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; fromX, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; fromY, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; toX, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; toY)
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.fromX &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; fromX;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.fromY &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; fromY;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.toX &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; toX;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.toY &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; toY;
        }
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Dibujando con VPL&lt;/h3&gt;
&lt;p&gt;El Visual Programming Language es una herramienta fascinante, lleno de &amp;quot;features&amp;quot;. Se puede arrastrar y soltar services components desde la toolbar. Cuando esta herramienta es lanzada, se puede buscar el DssScribble service en el área inferior izquierda:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dssscribvpl3.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Arrastré dos instancias del DssScribble service component, y las renombre a DssScribble1 y DssScribble2:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dssscribvpl2.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Conecté las instancias, así pueden escuchar sus notificaciones. Cada línea producida en una instancia es transmitida a la otra. De esta manera, lo que dibujemos en una ventana, aparecerá en la otra.&lt;/p&gt;
&lt;p&gt;La conexión es entre la notificación PostLine y la notificación NewLine:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dssscribconn.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Para lanzar la aplicación, ir al menú&amp;nbsp;&lt;strong&gt;Run -&amp;gt; Start.&lt;/strong&gt; Aparece una ventana, mostrando el log de mensajes:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dssscribrun.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;Esperamos unos momentos, y dos instancias del&amp;nbsp;componente DssScribble son creados, cada uno mostrando un formulario. Podemos dibujar en cualquiera de los dos, arrastrando el mouse, siendo reproducido el dibujo en el otro formulario:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dssscribwin.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;Este es mi autorretrato: una lágrima se me escapa, de la emoción de un dibujo distribuido.... ;-)&lt;/p&gt;
&lt;h3&gt;Ejecutando en nodos distribuidos&lt;/h3&gt;
&lt;p&gt;La IDE del VPL IDE tiene un diseñador de nodo. A la derecha, hay una rama Node en el árbol del proyecto. Cada nodo representa un DSS host conteniendo servicios DSS. Agregué dos nodos, el primero conteniendo una instancia del Scribble y arrastré la segunda instancia al segundo nodo:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dssscribvpl1.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;Noten el panel inferior derecho: definí ahí las propiedades para el nodo Windows0, en el mismo localhost, pero con otras puertas (el primer nodo correrá en las puertas 50000/50001). En otro proyecto, probé tener una máquina remota, y la aplicación distribuida funcionó sin problemas. Podemos definir varios nodos, cada uno en una máquina distintas, poner en ellos instancias de DssScribble, enlazarlas por notificaciones, y podemos dibujar con nuestro compañeros de trabajo.... ;-)&lt;/p&gt;
&lt;p align="left"&gt;Para ejecutar la aplicación en forma distribuida, se debe compilarla. Usar el menú&amp;nbsp;&lt;strong&gt;Build -&amp;gt; Compile as a Service &lt;/strong&gt;. Debe ingresarse un directorio donde generar el código y la solución. Entonces, la herramienta VPL compila solución, y genera los paquetes de instalación. Se puede abrir la solución generada con Visual Studio (el código es muy interesante, bastante astuto, implementando, por lo que ví, una máquina de pila, ver los métodos Decrement, Increment).&lt;/p&gt;
&lt;p align="left"&gt;Cada nodo debe tener corriendo un servicio llamado package deployer, que ejecuta en otra puerta (la misma para todos los nodos, el valor asumido es 55555). Ir a ejecutar el directorio bin de Microsoft Robotics Developer Studio, y ejecutar el &lt;strong&gt;rundeployer.cmd&lt;/strong&gt;:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dssscribrd.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align="left"&gt;Nota: si queremos compilar el servicio de nuevo, debemos parar el deployer: el generador de código usa el directorio bin y trae conflictos con el deployer andando.&lt;/p&gt;
&lt;p align="left"&gt;Ahora, estamos listos para distribuir nuestra &amp;quot;killer app&amp;quot;: ejecutar &lt;strong&gt;Run -&amp;gt; Run on distributed nodes. &lt;/strong&gt;El sistema avisa de tener los deployers ya andando:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dssscribwarn.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;Y la magia comienza: cada nodo es contactado, y la aplicación es instalada en ellos. Un nodo DSS es iniciado en cada nodo, y sus correspondientes instancias de servicios son creadas. En este ejemplo, tendremos dos nuevas ventanas de consola, ejecutando cada una un nodo DSS. Esta es la ventana de mi segundo nodo:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dssscribhost.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;Ahora, cada noda muestra su ventana de dibujo, y la diversión comienza.... :-)&lt;/p&gt;
&lt;h3&gt;Notas&lt;/h3&gt;
&lt;p&gt;No estoy usando partners en este ejemplo. En cambio, uso notificaciones de eventos, en este caso, nuevas líneas, así otros componentes pueden recibir esas notificaciones. Podemos escribir otros componentes, otras ventanas de dibujo, para recibir y procesar las líneas. Una idea es&amp;nbsp;usar las coordenadas de una nueva línea para controlar el motor de un robot, o para persistir las líneas producidas usando un componente de persistencia nuestro. Para controlar el motor de un robot, podemos usar VPL, sin necesidad de reescribir el componente original.&lt;/p&gt;
&lt;h3&gt;Conclusiones&lt;/h3&gt;
&lt;p&gt;Usando VPL podemos componer nuevas aplicaciones usando componentes ya existentes. Podemos crear nuestras propias actividades. Y usando diagramas de nodos (en VPL o usando el DSS Manifest Editor) con el packager deployer, podemos distribuir la aplicación en muchos físicos nodos, en cualquier manera que creamos conveniente. Pero debemos definir cada nodo y componente: no hay facilidades para programar una grilla, con nodos dinámicos. Una aplicacion gridificada para DSS puede ser escrita, pero en mi opinión, debe ser creada con código nuestro. Idea para explorar: escribir una aplicación de control, usando package deployer, instalara tareas en los nodos en una grilla.&lt;/p&gt;
&lt;p&gt;Todas estas herramientas abrieron mi cabeza. Escribir DSS services components es una nueva forma de pensar y programar, algo que quise explorar por años: cómo escribir objetos con un proceso de mensajes de una vía, en una forma distribuida y paralala (&lt;a href="http://ajlopez.wordpress.com/category/ajagents/" target="_blank"&gt;AjAgents&lt;/a&gt; está motivado por esa objetivo). Me imagino un sistema que modele las ideas de Minsky sobre la mente humana.&lt;/p&gt;
&lt;p&gt;Bueno, es un nuevo mundo.&amp;nbsp;Dorothy: no estamos más en Kansas... ;-)&lt;/p&gt;
&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1607097" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Decentralized+Software+Services/default.aspx">Decentralized Software Services</category></item><item><title>Algoritmos Genéticos con AjAgents y Concurrency and Coordination Runtime (CCR)</title><link>http://msmvps.com/blogs/lopez/archive/2008/04/13/algoritmos-gen-233-ticos-con-ajagents-y-concurrency-and-coordination-runtime-ccr.aspx</link><pubDate>Sun, 13 Apr 2008 15:03:48 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1585477</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1585477</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/04/13/algoritmos-gen-233-ticos-con-ajagents-y-concurrency-and-coordination-runtime-ccr.aspx#comments</comments><description>&lt;p&gt;El año pasado había implementado un ejemplo con AjAgents usando CCR:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2007/10/20/agentes-usando-concurrency-and-coordination-runtime-ccr.aspx" target="_blank"&gt;Agentes usando Concurrency and Coordination Runtime (CCR)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ajlopez.wordpress.com/2007/10/17/agents-using-concurrency-and-coordination-runtime-ccr/" target="_blank"&gt;Agents using Concurrency and Coordination Runtime (CCR)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Escribí en mi blog en &amp;quot;anglish&amp;quot; (Angel&amp;#39;s English) algunas ideas para explorar:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ajlopez.wordpress.com/2008/01/03/agents-in-a-grid/" target="_blank"&gt;Agents in a Grid&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Recordemos que Concurrency and Coordination Runtime es parte de Microsoft Robotics Studio, puede leer más sobre esta librería en&lt;/p&gt; &lt;p&gt;&lt;a href="http://msdn.microsoft.com/msdnmag/issues/06/09/ConcurrentAffairs/default.aspx" target="_blank"&gt;Concurrent Affairs: Concurrency and Coordination Runtime&lt;/a&gt;&lt;/p&gt; &lt;p&gt;y consultar mis enlaces de Delicious&lt;/p&gt; &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/ccr"&gt;http://del.icio.us/ajlopez/ccr&lt;/a&gt;&lt;br /&gt;&lt;a href="http://del.icio.us/ajlopez/msrs"&gt;http://del.icio.us/ajlopez/msrs&lt;/a&gt;&lt;/p&gt; &lt;p&gt;En estos días, extendí mi ejemplo &lt;a title="AjAgentsCCR-0.1.zip" href="http://www.ajlopez.com/downloads/AjAgentsCCR-0.1.zip"&gt;AjAgentsCCR-0.1.zip&lt;/a&gt;&amp;nbsp;con dos nuevos proyectos. Uno de consola AjAgents.Genetic01, y otro de ventanas AjAgents.WinGenetic01:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajagentsga02.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;La idea básica es ejecutar un algoritmo genético usando agentes, los elementos de AjAgents, que se envían mensajes usando ports de CCR. Cada agente procesa sus mensajes entrantes, y envía mensajes salientes a otros agentes, en paralelo. El problema que encaro es el clásico &lt;a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem" target="_blank"&gt;Travelling Salesman Problem&lt;/a&gt;. Leo en la Wikipedia:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;If a salesman starts at point A, and if the distances between every pair of points are known, what is the shortest route which visits all points and returns to point A?&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;La ventana de ejemplo es sencilla:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajagentsga01.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;La clase Genoma representa el viaje&amp;nbsp;(una lista de Points y un valor de distancia total):&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:4d8bdf80-11fc-428c-bfba-85e5d279f9c0" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; Genoma
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; List&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Point&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; travel &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; List&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Point&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;();
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; value;
    }

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; Point
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; x;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; y;
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Al comenzar la ejecución, los agentes son creados y conectados:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:2a22c08b-84d4-4d08-b508-f9fb3b2b8e77" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;            best &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; BestSoFar();
            evaluator &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Evaluator();
            mutator &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Mutator();
            collector &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Collector();

            evaluator.Collector &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; collector;
            collector.Mutator &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; mutator;
            collector.Evaluator &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; evaluator;
            collector.BestSoFar &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; best;
            mutator.Evaluator &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; evaluator;
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Un genoma inicial es creado:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:deb88aff-6fe9-42b9-9f78-a48ef43ef78a" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;            Genoma genoma &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Genoma();
            Random rnd &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Random();

            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; k &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;; k&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;40&lt;/span&gt;&lt;span style="color:#000000;"&gt;; k&lt;/span&gt;&lt;span style="color:#000000;"&gt;++&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
                {
                    Point pt &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Point();
                    pt.x &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; rnd.Next(&lt;/span&gt;&lt;span style="color:#000000;"&gt;12&lt;/span&gt;&lt;span style="color:#000000;"&gt;);
                    pt.y &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; rnd.Next(&lt;/span&gt;&lt;span style="color:#000000;"&gt;12&lt;/span&gt;&lt;span style="color:#000000;"&gt;);

                    genoma.travel.Add(pt);
                }

            genoma.value &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; evaluator.CalculateValue(genoma);
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;El agente BestSoFar dispara un evento. El formulario se registra como observador de ese evento, para refrescar el mejor viaje calculado y dibujarlo. El programa envía el genoma inicial generado al agente Mutator, varias veces, para generar la primeras poblaciones:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:79e9473d-f8f8-4426-8281-75c536583015" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;            best.NewBest &lt;/span&gt;&lt;span style="color:#000000;"&gt;+=&lt;/span&gt;&lt;span style="color:#000000;"&gt; BestGenoma;

            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; k &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;; k &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;60&lt;/span&gt;&lt;span style="color:#000000;"&gt;; k&lt;/span&gt;&lt;span style="color:#000000;"&gt;++&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
            {
                mutator.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Mutate&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, genoma);
            }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Noten el uso del método Post, básico en AjAgents. Cada agente implementa ese método, que invoca&amp;nbsp;un método en el agente,&amp;nbsp;usando una puerta de CCR para invocar el método final. El método es ejecutado entonces no en el momento, sino en&amp;nbsp;forma &amp;quot;paralela&amp;quot;, en un thread&amp;nbsp;que maneja el pool de threads de CCR.&lt;/p&gt;
&lt;p&gt;Un diagrama simple para explicar la interacción entre agentes:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajagentsga03.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;El Mutator envía cada genoma al Evaluator. Este agente calcula el valor asignado a ese genoma. Lo envía a el Collector. Este implementa una nueva idea para este ejemplo: en vez de tener una clase Population o similar, el Collector recive genomas, y cuando tiene n o más genomas, determina los mejores del conjunto, envía el mejor a BestSoFar, y reenvía los mejores a Mutator, para generar una nueva lista de genomas a evaluar.&amp;nbsp;Como método típico de ejemplo, tomemos uno de la clase Collector:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:f7ff20f4-a441-44e2-86a5-ebad4bd4b4ba" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ProcessList(List&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Genoma&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; list)
        {
            list.Sort(comparer);

            bestsofar.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Process&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,list[&lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;]);

            evaluator.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Evaluate&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,list[&lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;]);
            evaluator.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Evaluate&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,list[&lt;/span&gt;&lt;span style="color:#000000;"&gt;1&lt;/span&gt;&lt;span style="color:#000000;"&gt;]);

            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt; k &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;; k &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;4&lt;/span&gt;&lt;span style="color:#000000;"&gt;; k&lt;/span&gt;&lt;span style="color:#000000;"&gt;++&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
            {
                mutator.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Mutate&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,list[k]);
                mutator.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Mutate&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,list[k]);
            }
        }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Tengo que mejorar el algoritmo genético. Ahora, sólo usa mutación, sin hacer &amp;quot;crossover&amp;quot; (cruzamiento) entre los mejores genomas. El resultado que consigue ahora, no es óptimo: puede dar como resultado un máximo local, pero no la mejor solución. La idea del ejemplo es ver ejecutando AjAgents con CCR, en una prueba de concepto.&lt;/p&gt;
&lt;h3&gt;Conclusiones&lt;/h3&gt;
&lt;p&gt;Uno puede ver cada agente como una pequeña célula u organismo, que reacciona a mensajes externos y envía mensajes a otros agentes. Cada agente está levemente acoplado a los demás. En estos ejemplos, los agentes son creados y relaciones por código, pero bien podrían ser creados y relacionados usando algún framework de inyección de dependencias, como &lt;a href="http://www.springframework.net" target="_blank"&gt;Spring.NET&lt;/a&gt; o el nuevo&amp;nbsp;&lt;a href="http://msdn2.microsoft.com/en-us/library/cc468366.aspx" target="_blank"&gt;Unity Application Block&lt;/a&gt; de Microsoft.&lt;/p&gt;
&lt;p&gt;En lugar de usar solamente ports de CCR, podría escribir los agentes como&amp;nbsp; DSS Service components (ver &lt;a href="http://www.microsoft.com/robotics" target="_blank"&gt;Microsoft Robotics Studio&lt;/a&gt; para más información sobre DSS); el algoritmo podría ser distribuido en una grilla (&amp;quot;gridified&amp;quot;) y cada agente interactuar con otros, independientemente de su ubicación..&lt;/p&gt;
&lt;p&gt;Pero eso es otra historia....;-)&lt;/p&gt;
&lt;p&gt;En esta semana, ha sido anunciada la nueva versión de Microsoft Robotics Developer Studio 2008:&lt;/p&gt;
&lt;p&gt;&lt;a title="http://blogs.msdn.com/msroboticsstudio/archive/2008/04/09/microsoft-robotics-developer-studio-2008-ctp-april-available.aspx" href="http://blogs.msdn.com/msroboticsstudio/archive/2008/04/09/microsoft-robotics-developer-studio-2008-ctp-april-available.aspx"&gt;http://blogs.msdn.com/msroboticsstudio/archive/2008/04/09/microsoft-robotics-developer-studio-2008-ctp-april-available.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;La tercera nueva característica ahí anunciada, sería muy interesante para implementar &amp;quot;miniagentes&amp;quot; distribuidos:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Support for creating applications that run on multiple DSS nodes using Visual Programming Language and DSS Manifest Editor. This makes it much simpler to create applications that run across nodes, either on the same machine or across the network. When an application containing multiple nodes is to be started, VPL creates individual deploy packages for each node and fires them up across the network.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;(este artículo es la versión en español de mi versión &amp;quot;anglish&amp;quot;:&lt;br /&gt;&lt;a href="http://ajlopez.wordpress.com/2008/04/10/genetic-algorithms-with-ajagents-and-concurrency-and-coordination-runtime-ccr/" target="_blank"&gt;Genetic Algorithms with AjAgents and Concurrency and Coordination Runtime (CCR)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1585477" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjAgents/default.aspx">AjAgents</category></item><item><title>Agentes usando Concurrency and Coordination Runtime (CCR)</title><link>http://msmvps.com/blogs/lopez/archive/2007/10/20/agentes-usando-concurrency-and-coordination-runtime-ccr.aspx</link><pubDate>Sat, 20 Oct 2007 00:24:29 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1251823</guid><dc:creator>lopez</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1251823</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2007/10/20/agentes-usando-concurrency-and-coordination-runtime-ccr.aspx#comments</comments><description>&lt;p&gt;En estos días, escribí un ejemplo mínimo, para explorar algunas ideas, usando el Concurrency and Coordination Runtime, la librería de Microsoft library&amp;nbsp;que viene en&amp;nbsp;su Robotics Studio. Más sobre CCR en el artículo:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msdn.microsoft.com/msdnmag/issues/06/09/ConcurrentAffairs/default.aspx" target="_blank"&gt;Concurrent Affairs: Concurrency and Coordination Runtime&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Mi idea es implementar el pase de mensajes entre componentes, de manera asincrónica. El código de ejemplo puede bajarse de &lt;a href="http://www.ajlopez.com/downloads/AjAgentsCCR-0.1.zip"&gt;AjAgentsCCR-0.1.zip&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;El agente&lt;/h3&gt; &lt;p&gt;En el ejemplo, la interfaz a implementar por cada componente, que llamamos agente, es:&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:e34cc818-2db0-4674-b32e-9afb83a6646e" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;delegate&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; ReturnHandler&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;T&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(T t);

&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;interface&lt;/span&gt;&lt;span style="color:#000000;"&gt; IAgent
{
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Post(Message msg);
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Post(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; action, 
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;params&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt;[] parameters);
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;void&lt;/span&gt;&lt;span style="color:#000000;"&gt; Post&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;T&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; action, 
        ReturnHandler&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;T&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; handler, 
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;params&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt;[] parameters);
}
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;El agente puede recibir mensajes (que son objetos de una clase Message, ver más abajo). En el mensaje viene un texto con la Action a ejecutar (como si fuera un nombre de método) y una lista&amp;nbsp;variable de parámetros.&lt;/p&gt;
&lt;p&gt;El tercer método Post implementa un delegado, un método a ejecutar cuando el envío del mensaje produce una respuesta, un valor de retorno. Esa vuelta se produce en el futuro, no se queda esperando la respuesta. Podemos enviar un mensaje a otro agente, sin esperar la respuesta, o podemos escribir el delegado para procesar esa respuesta cuando llegue.&lt;/p&gt;
&lt;h3&gt;El mensaje&lt;/h3&gt;
&lt;p&gt;Es una clase con&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font color="#333333"&gt;&lt;strong&gt;action&lt;/strong&gt;: un nombre que identifica la acción asociada al mensaje&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#333333"&gt;&lt;strong&gt;body&lt;/strong&gt;: el contenido del mensaje&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font color="#333333"&gt;&lt;strong&gt;response port&lt;/strong&gt;: la puerta CCR donde enviar el valor de retorno, si es necesario&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;He aquí el código de esta clase:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:6965b573-91b2-438f-98bd-aef1e84dce57" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; Message
{
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; action;

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; Action
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt; { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; action; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt; { action &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; value; }
    }

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; body;

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; Body
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt; { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; body; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt; { body &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; value; }
    }

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; Port&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; returnport;

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;internal&lt;/span&gt;&lt;span style="color:#000000;"&gt; Port&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; ReturnPort
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt; { &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; returnport; }
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt; { returnport &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; value; }
    }
    

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; Message()
    {
    }

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; Message(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; action)
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.action &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; action;
    }

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; Message(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; action, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt; body)
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.action &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; action;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.body &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; body;
    }

    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; Message(&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;string&lt;/span&gt;&lt;span style="color:#000000;"&gt; action, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;object&lt;/span&gt;&lt;span style="color:#000000;"&gt;[] bodyvalues)
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.action &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; action;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; (bodyvalues &lt;/span&gt;&lt;span style="color:#000000;"&gt;!=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color:#000000;"&gt; bodyvalues.Length &lt;/span&gt;&lt;span style="color:#000000;"&gt;==&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;1&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.body &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; bodyvalues[&lt;/span&gt;&lt;span style="color:#000000;"&gt;0&lt;/span&gt;&lt;span style="color:#000000;"&gt;];
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;else&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;this&lt;/span&gt;&lt;span style="color:#000000;"&gt;.body &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; bodyvalues;
    }
}
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Notemos que el mensaje tiene&amp;nbsp;puede manejar un arreglo de valores en el body, y que puede enviar un objeto dentro de&amp;nbsp;su contenido.&lt;/p&gt;
&lt;h3&gt;La implementación&lt;/h3&gt;
&lt;p&gt;En este ejemplo inicial, la interfaz IAgent tiene una implementación basado en Invoke, via Reflection, que termina invocando un método en el agente, que tiene el mismo nombre que la acción recibida. Se pueden pensar otras formas de manejar el mensaje, pero esta manera permite codificar el agente como una clase más, con métodos normales.&lt;/p&gt;
&lt;p&gt;El mensaje, una vez recibido, se coloca en una puerta CCR, para que se pueda manejar de manera asincrónica. Hay un Receive arbiter de CCR para atender los mensajes entrantes, que son ruteados al correspondiente método en el objeto.&lt;/p&gt;
&lt;p&gt;Creo que es una solución interesante: se puede escribir una clase con métodos normales, y convertirla en agente, heredando de la clase Agent.&lt;/p&gt;
&lt;p&gt;Podemos enviar un mensaje con&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:b915dcf3-1163-4974-87f5-96ffeff4e3a1" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;agent1.Post(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Decrement&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,&lt;/span&gt;&lt;span style="color:#000000;"&gt;20&lt;/span&gt;&lt;span style="color:#000000;"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Puede &amp;quot;consultar&amp;quot; algún valor con:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:263c231a-b09a-43ba-89e6-feec1f546fef" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;agent1.Post&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;GetCounter&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, PrintCounter);
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Próximos pasos&lt;/h3&gt;
&lt;p&gt;Estoy trabajando en:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Escribir un&amp;nbsp;Enviroment, o clase Host, donde los agentes &amp;quot;vivan&amp;quot;. El Host sería responsable de mantener una lista de agentes por nombre. 
&lt;li&gt;Escribir un archivo de configuración donde pueda especificar qué agentes crear y cargar a comenzar a funcionar el Environment o Host, y que los relacione usando alguna implementación de inyección de dependencias. Me imagino servidores de agentes que pueda cargar un agente remoto de assemblies que se encuentren en otros servidores de la red. 
&lt;li&gt;Usar estos agentes en forma distribuida, con&amp;nbsp;Windows Communication Foundation (WCF), o con&amp;nbsp;Decentralized System Services (DSS). En este último caso, un servicio DSS podría ser un agente o podría representar la entrada a un Environment 
&lt;li&gt;Implementar&amp;nbsp;algún&amp;nbsp;patrón Subscribe/Notify entre agentes.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1251823" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjAgents/default.aspx">AjAgents</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp.NET/default.aspx">C Sharp.NET</category></item></channel></rss>