<?xml version="1.0" encoding="iso-8859-15"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"><channel><title>blogs.ASPItalia.com</title><link>http://blogs.aspitalia.com//ricciolo//</link><description>blogs.ASPItalia.com</description><language>it-it</language><copyright>1998-2013 ASPItalia.com/blogs.ASPItalia.com</copyright><generator>Generated by feed.ASPItalia.com 'Cortana' 2013.5.16</generator><sy:updatePeriod>hourly</sy:updatePeriod><sy:updateFrequency>1</sy:updateFrequency><sy:updateBase>1998-01-01T12:00+00:00</sy:updateBase><lastBuildDate>Fri, 11 Mar 2011 17:42:00 GMT</lastBuildDate><image><title>blogs.ASPItalia.com</title><url>http://gui.aspitalia.com/images/aspitalia/syndication.gif</url><link>http://blogs.aspitalia.com//ricciolo//</link></image><item><title>LINQ, lazy loading e architettura</title><link>http://blogs.aspitalia.com/ricciolo/post2690/LINQ-Lazy-Loading-Architettura.aspx</link><pubDate>Fri, 11 Mar 2011 17:42:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2690" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Con l'avvento di LINQ l'accesso ai dati è decisamente cambiato. Con un timido &lt;b&gt;LINQ to SQL&lt;/b&gt; e un po' più maturo &lt;b&gt;LINQ to Entities&lt;/b&gt; abbiamo potuto interrogare le informazioni sfruttando ORM, oggetti, tipizzazione, compilazione delle query e tutti i benefici che ormai sappiamo.&lt;/p&gt;&lt;p&gt;Anche LINQ con il tempo ha dovuto trovare il suo posto e adattare/adattarsi hai layer e ai pattern che usiamo da tempo e, a mio avviso, si è trovato un ottimo compromesso che permetta di conciliare astrazione e la facilità di LINQ. Mi riferisco alla tipica separazione in layer che solitamente si fa tra repository, servizi di dominio e servizi applicativi che ha trovato alleato l'utilizzo dell'interfaccia &lt;b&gt;IQueryable&lt;/b&gt; per essere restituito dal repository e permette ai vari strati di aggiungere pezzi alla query per poter essere poi eseguita quando effettivamente la consumiamo.&lt;/p&gt;&lt;p&gt;Il nostro &lt;a href="http://blogs.aspitalia.com/cradle/"&gt;MarcoDes&lt;/a&gt; ha inserito questa tecnica in &lt;a href="http://modelvirtualcasting.codeplex.com/"&gt;Model Virtual Casting&lt;/a&gt;, e si dimostra molto comoda ed efficace se utilizzata con LINQ to Entities. Non voglio però parlare di questo dal punto di vista architetturale ma affrontare un problema tecnologico che ho dovuto affrontare. Quando infatti utilizziamo IQueryable ci ritroviamo con la problematica principale di dover indicare quali navigation property caricare all'interno delle entità che si stanno materializzando e, scartando l'ipotesi del &lt;b&gt;lazy loading&lt;/b&gt; per motivi di controllo ed efficienza&amp;#xa0;sulle query, si procede con l'indicare sul repository le proprietà da includere. Anche questo è implementato&amp;#xa0;in Model Virtual Casting e l'abbiamo rappresentato con un'interfaccia simile a questa.&lt;/p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;public&lt;/span&gt; &lt;span style="color:#0000FF"&gt;interface&lt;/span&gt; IReadOnlyRepository&amp;lt;T&amp;gt;
{
  IQueryable&amp;lt;T&amp;gt; GetAll();
  IReadOnlyRepository&amp;lt;T&amp;gt; Include(&lt;span style="color:#0000FF"&gt;string&lt;/span&gt; path);
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Esiste una variante che al posto della stringa richiede un &lt;b&gt;Expression&lt;/b&gt; per rendere tutto tipizzato, ma in sostanza il discorso non cambia. Quando da un servizio utilizziamo il repository di fatto faremo:&lt;/p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;IQueryable&amp;lt;Product&amp;gt; list = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; ProductRepository().Include(&amp;quot;&lt;span style="color:#8B0000"&gt;Orders&lt;/span&gt;&amp;quot;).GetAll();&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In questo modo, quando sfogliamo list otteniamo popolata la classe Product con i rispettivi ordini attraverso la collezione esposta dalla proprietà Orders. Poiché l'implementazione del repository è basta su EF 40, la chiamata ad Include si traduce semplicemente alla chiamata alla funzione omonima di ObjectQuery&amp;lt;T&amp;gt; di LINQ to Entities.&lt;/p&gt;
&lt;p&gt;Il problema di questo è approccio è che qualora decidiamo di restituire la variabile list, facendola passare ad esempio dallo strato dei servizi a quello applicativo per effettuare un binding, perdiamo il riferimento al repository e di conseguenza la possibilità di aggiungere &lt;b&gt;Include&lt;/b&gt; anche su strati successivi. Se gli strati che si passano IQueryable e alterano la query non fanno altro che agire solo sull'expression tree, non è più probabile che sia l'utilizzatore finale a sapere quali proprietà si debba materializzare? A mio modo di vedere la risposta è sì e lo dimostra anche il fatto che spesso si utilizzano proezioni per ottenere un sottoinsieme dei membri disponibili su una classe.&lt;/p&gt;
&lt;p&gt;Per permettere quindi di effettuare gli Include su tutti gli strati ho pensato dapprima a la creazione di un'inferfaccia IMultiQueryable&amp;lt;T&amp;lt; che ereditando da IQueryable permetta sia di effettuare query ma anche di effettuare Include. Questa soluzione l'ho adottata con un cliente e si è dimostrata sempre funzionante portando solo con se la scomodità di fare il cast in certe situazioni su IMultiQueryable. Ho dunque pensato ad una soluzione alternativa che praticamente consiste nel creare un extension method personalizzato per rappresentare l'include:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;public&lt;/span&gt; &lt;span style="color:#0000FF"&gt;static&lt;/span&gt; IQueryable&amp;lt;T&amp;gt; Include&amp;lt;T&amp;gt;(&lt;span style="color:#0000FF"&gt;this&lt;/span&gt; IQueryable&amp;lt;T&amp;gt; source, &lt;span style="color:#0000FF"&gt;params&lt;/span&gt; Expression&amp;lt;Func&amp;lt;T, Object&amp;gt;&amp;gt;[] properties)
{
  MethodInfo method = ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(&lt;span style="color:#0000FF"&gt;new&lt;/span&gt; Type[] { &lt;span style="color:#0000FF"&gt;typeof&lt;/span&gt;(T) });
  var arguments = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; Expression[] {
    source.Expression,
    Expression.NewArrayInit(&lt;span style="color:#0000FF"&gt;typeof&lt;/span&gt;(Expression&amp;lt;Func&amp;lt;T, Object&amp;gt;&amp;gt;), properties.Select(p =&amp;gt; Expression.Quote(p))),
  };

  &lt;span style="color:#0000FF"&gt;return&lt;/span&gt; source.Provider.CreateQuery&amp;lt;T&amp;gt;(Expression.Call(&lt;span style="color:#0000FF"&gt;null&lt;/span&gt;, method, arguments));
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In modo simile a Where, OrderBy ecc, non faccio altro che creare un'espressione che chiama il metodo stesso Include. Questo mi permette di eliminare tale metodo dall'interfaccia di repository e di scrivere, ovunque sono, il seguente codice:
&lt;div class="codebox"&gt;&lt;pre&gt;IQueryable&amp;lt;Product&amp;gt; list = GetProductsFromRespository();
list = list.Include(p =&amp;gt; p.Orders).Take(10).Include(p =&amp;gt; p.Details);&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Possiamo quindi combinare Include come qualsiasi altro extension method, su qualsiasi layer, basta che sia un IQueryable. E' chiaro però che così facendo quando LINQ to Entities dovrà convertire l'expression tree in SQL, non conoscerà il nostro metodo personalizzato e lancerà un'eccezione. Aggirare il problema però è più semplice di quanto si pensi, perché basta fornire un intermediario all'oggetto iniziale della query.&lt;/p&gt;
&lt;p&gt;Mettendoci a livello del repository possiamo infatti non restituire direttamente l'ObjectQuery restituito dall'ObjectContext di EF, ma restituire un wrapper da noi creato che implementa IQueryable.&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;public&lt;/span&gt; IQueryable&amp;lt;Product&amp;gt; GetAll()
{
  NorthwindContext c = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; NorthwindContext();
  &lt;span style="color:#0000FF"&gt;return&lt;/span&gt; &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; ObjectMultiQuery&amp;lt;T&amp;gt;(c.Products);
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Implementare IQueryable se si deve fare solo da intermediari è piuttosto semplice, perché la nostra unica intenzione è porci in mezzo prima di eseguire la query su database. Per farlo dobbiamo implementare &lt;b&gt;IEnumerable.GetEnumerator&lt;/b&gt; e &lt;b&gt;IQueryProvider.Execute&lt;/b&gt;, alterare l'espression tree creato e passarlo al motore di LINQ to Entities per eseguirla.&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;public&lt;/span&gt; IEnumerator&amp;lt;T&amp;gt; GetEnumerator()
{
  &lt;span style="color:#008000"&gt;// Trasformo l&amp;#39;espressione per LINQ to Entities&lt;/span&gt;
  IncludeVisitor compiler = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; IncludeVisitor();
  Expression newExpression = compiler.Visit(&lt;span style="color:#0000FF"&gt;this&lt;/span&gt;.Expression);

  &lt;span style="color:#008000"&gt;// Creo la nuova query utilizzando ObjectQuery&amp;lt;T&amp;gt;&lt;/span&gt;
  IEnumerable&amp;lt;T&amp;gt; result = &lt;span style="color:#0000FF"&gt;this&lt;/span&gt;.original.Provider.CreateQuery&amp;lt;T&amp;gt;(newExpression) &lt;span style="color:#0000FF"&gt;as&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt;;

  &lt;span style="color:#008000"&gt;// Ottengo il risultato&lt;/span&gt;
  &lt;span style="color:#0000FF"&gt;return&lt;/span&gt; result.GetEnumerator();
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Il campo original è l'oggetto originale EF ottenuto con c.Products nel codice precedente e rappresenta l'engine di EF. La classe IncludeVisitor invece ha il compito di trasformare l'espressione, cioè tradurre le chiamate all'extension method Include, al metodo ObjectQuery.Include. Ci viene in aiuto la classe &lt;b&gt;ExpressionVisitor&lt;/b&gt; dalla quale possiamo ereditare e sovrascrivere il metodo VisitMethodCall per cambiare l'espressione di chiamata. Riporto il codice con i commenti così da capire meglio come funziona:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;class&lt;/span&gt; IncludeVisitor : ExpressionVisitor
{
  &lt;span style="color:#0000FF"&gt;protected&lt;/span&gt; &lt;span style="color:#0000FF"&gt;override&lt;/span&gt; Expression VisitMethodCall(MethodCallExpression node)
  {
    &lt;span style="color:#0000FF"&gt;if&lt;/span&gt; (node.Method.DeclaringType == &lt;span style="color:#0000FF"&gt;typeof&lt;/span&gt;(Extensions) &amp;amp;&amp;amp; node.Method.Name == &amp;quot;&lt;span style="color:#8B0000"&gt;Include&lt;/span&gt;&amp;quot;)
    {
      PropertiesVisitor visitor = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; PropertiesVisitor();

      &lt;span style="color:#008000"&gt;// ObjectQuery&amp;lt;T&amp;gt;&lt;/span&gt;
      Type objectQueryType = &lt;span style="color:#0000FF"&gt;typeof&lt;/span&gt;(ObjectQuery&amp;lt;&amp;gt;).MakeGenericType(node.Arguments[0].Type.GetGenericArguments());
      &lt;span style="color:#008000"&gt;// Visito il context cos&amp;#236; conto anch&amp;#39;esso come parametro&lt;/span&gt;
      &lt;span style="color:#008000"&gt;// Effettuo un convert per essere sicuro che sia un ObjectQuery&amp;lt;T&amp;gt;&lt;/span&gt;
      Expression exp = Expression.Convert(&lt;span style="color:#0000FF"&gt;this&lt;/span&gt;.Visit(node.Arguments[0]), objectQueryType);

      &lt;span style="color:#008000"&gt;// Trovo il metodo include specifico di ObjectQuery&amp;lt;T&amp;gt;&lt;/span&gt;
      MethodInfo includeMethod = objectQueryType.GetMethod(&amp;quot;&lt;span style="color:#8B0000"&gt;Include&lt;/span&gt;&amp;quot;, BindingFlags.Public | BindingFlags.Instance);

      &lt;span style="color:#008000"&gt;// Chiama il metodo Include per tutte le espressioni passate&lt;/span&gt;
      &lt;span style="color:#0000FF"&gt;foreach&lt;/span&gt; (var property &lt;span style="color:#0000FF"&gt;in&lt;/span&gt; ((NewArrayExpression)node.Arguments[1]).Expressions)
      {
        visitor.FindProperties(property);

        &lt;span style="color:#008000"&gt;// Concateno le propriet&amp;#224; trovate con il punto&lt;/span&gt;
        exp = Expression.Call(exp, includeMethod, Expression.Constant(String.Join(&amp;quot;&lt;span style="color:#8B0000"&gt;.&lt;/span&gt;&amp;quot;, visitor.PropertyNames)));
      }

      &lt;span style="color:#0000FF"&gt;return&lt;/span&gt; exp;
    }
    &lt;span style="color:#0000FF"&gt;return&lt;/span&gt; &lt;span style="color:#0000FF"&gt;base&lt;/span&gt;.VisitMethodCall(node);
  }
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In questo modo l'expression tree originale cambia così:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#008000"&gt;// Da&lt;/span&gt;
Convert(&lt;span style="color:#0000FF"&gt;value&lt;/span&gt;(System.Data.Objects.ObjectSet`1[Product])).MergeAs(AppendOnly).Include(&lt;span style="color:#0000FF"&gt;new&lt;/span&gt; [] {c =&amp;gt; c.Orders}).Take(10)
&lt;span style="color:#008000"&gt;// A&lt;/span&gt;
Convert(Convert(&lt;span style="color:#0000FF"&gt;value&lt;/span&gt;(System.Data.Objects.ObjectSet`1[Product])).MergeAs(AppendOnly)).Include(&amp;quot;&lt;span style="color:#8B0000"&gt;Orders&lt;/span&gt;&amp;quot;).Take(10)&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Trovo questa soluzione veloce ed efficace ed è soprattutto approvata da &lt;a href="http://blogs.aspitalia.com/cradle/"&gt;MarcoDes&lt;/a&gt; :-D. Trovate l'esempio nelle &lt;a href="http://lab.aspitalia.com/Ricciolo/Downloads/Codemotion11.zip"&gt;demo&lt;/a&gt; di Codemotion 2011 svoltosi a Roma pochi giorni fa. Enjoy!&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.0/" rel="tag"&gt;.NET Framework 4.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Architettura/" rel="tag"&gt;Architettura&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Entity_Framework/" rel="tag"&gt;Entity Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/LINQ/" rel="tag"&gt;LINQ&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/LINQ_to_Entities/" rel="tag"&gt;LINQ to Entities&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2690/LINQ-Lazy-Loading-Architettura.aspx"&gt;&lt;em&gt;LINQ, lazy loading e architettura&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, .NET Framework, .NET Framework 3.5, .NET Framework 4.0, Architettura, Entity Framework, LINQ, LINQ to Entities</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2690/LINQ-Lazy-Loading-Architettura.aspx</guid><slash:comments>1</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2690/LINQ-Lazy-Loading-Architettura.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2690.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2690</trackback:ping></item><item><title>MetadataDiffViewer: aggiornato al .NET Framework 4.0, Silverlight 4.0 e Sharepoint 2010</title><link>http://blogs.aspitalia.com/ricciolo/post2581/MetadataDiffViewer-Aggiornato-.NET-Framework-4.0-Silverlight-4.0-Sharepoint.aspx</link><pubDate>Thu, 07 Jan 2010 12:58:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2581" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Come promisi parecchio&lt;a href="http://blogs.aspitalia.com/ricciolo/post2483/MetadataDiffViewer-Differenze-Framework.aspx"&gt; tempo fa&lt;/a&gt;, sto mantenendo il &lt;a href="http://lab.ricciolo.aspitalia.com/metadatadiffviewer/metadatadiffviewer.html"&gt;MetadataDiffViewer&lt;/a&gt;, il tool realizzato in &lt;strong&gt;Silverlight&lt;/strong&gt; che permette di visualizzare le differenze tra le versioni dei framework.&lt;/p&gt;&lt;p&gt;Ho aggiornato prima di tutto il metodo di download dei metadati rendendolo più veloce e richiedendo meno spazio nello storage. Ora richiede la versione 3.0 di Silverlight e supporta il mouse wheel.&lt;/p&gt;&lt;p&gt;Anche i metadati sono stati aggiornati per supportare il .NET Framework 4.0 Beta 2, Silverlight 4.0 Beta 1 e Sharepoint 2010, comparati con le relative precedenti versioni.&lt;/p&gt;&lt;p&gt;Spero possa esservi utile per i vostri studi.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_2.0/" rel="tag"&gt;.NET Framework 2.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.0/" rel="tag"&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.0/" rel="tag"&gt;.NET Framework 4.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/SharePoint/" rel="tag"&gt;SharePoint&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2581/MetadataDiffViewer-Aggiornato-.NET-Framework-4.0-Silverlight-4.0-Sharepoint.aspx"&gt;&lt;em&gt;MetadataDiffViewer: aggiornato al .NET Framework 4.0, Silverlight 4.0 e Sharepoint 2010&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, .NET Framework, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5, .NET Framework 4.0, SharePoint</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2581/MetadataDiffViewer-Aggiornato-.NET-Framework-4.0-Silverlight-4.0-Sharepoint.aspx</guid><slash:comments>3</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2581/MetadataDiffViewer-Aggiornato-.NET-Framework-4.0-Silverlight-4.0-Sharepoint.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2581.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2581</trackback:ping></item><item><title>.NET Framework 4.0 beta 1: Windows Communication Foundation</title><link>http://blogs.aspitalia.com/ricciolo/post2498/.NET-Framework-4.0-Beta-1-Windows-Communication-Foundation.aspx</link><pubDate>Mon, 18 May 2009 14:00:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2498" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Vista l'imminente uscita del &lt;strong&gt;.NET Framework 4.0&lt;/strong&gt; beta 1 vediamo un po' tra le numerose novità, quali sono quelle che riguardano WCF.&amp;#xa0;Nonostate fino ad ora non è stata resa pubblica una build completa si conoscono già le principali nuove caratteristiche.&lt;/p&gt;&lt;p&gt;Si parte dai miglioramenti di prestazioni del &lt;strong&gt;DataContractSerializer&lt;/strong&gt;, motore principale per la serializzazione degli oggetti e un nuovo &lt;strong&gt;DataContractResolver&lt;/strong&gt; che permette di personalizzare la risoluzione dei tipi. La configurazione, punto dolente della prima versione, è stata semplificata. Ora è possibile definire un servizio e/o un behavior con name vuoto e si ottiene una configurazione predefinita per tutti i servizi dell'hosting. I file svc sono poi auto configuranti e ciò significa che viene creato automaticamente un endpoint basandosi sulle configurazioni predefinite dei servizi HTTP.&lt;/p&gt;&lt;p&gt;Sono disponibili poi nuovi binding e nuovi canali tra i quali la possibilità di fare &lt;strong&gt;HTTP polling duplex&lt;/strong&gt; (usato da Silverlight), di esporre un servizio tramite &lt;strong&gt;UDP&lt;/strong&gt;, un nuovo sistema di claim basato su &lt;strong&gt;Geneva&lt;/strong&gt;, nome in codice del nuovo framework per l'autenticazione e gestione dell'identità. WCF 4.0 aderisce alle specifiche &lt;strong&gt;Basic Profile 1.2&lt;/strong&gt; che garantiscono una migliore interoperabilità tra piattaforme diverse ed implementa inoltre &lt;strong&gt;WS-Discovery&lt;/strong&gt; e il routing. Il primo permette ad un servizio di annunciarsi attraverso endpoint conosciuti che i possibili client possono individuare ed andare a consumare. Con il servizio di routing è invece possibile porre uno strato intermedio che dirotti le richieste verso gli endpoint effettivi a seconda dei carichi od in base a regole XPath applicate sul messaggio.&lt;/p&gt;&lt;p&gt;WCF inoltre si accopia con Windows Workflow Foundation diventando praticamente un solo framework. Questo perché dall'idea di Workflow Services, introdotti con il service pack 1 del .NET Framework 3.5, si è passati ad una&amp;#xa0;forte cooperazione ed integrazione tra le tue tecnologie. Partecipano allo stesso sistema di tracing e di tracking, di gestione degli errori, di transazione e sfruttando &lt;strong&gt;WAS&lt;/strong&gt; e tutti gli strumenti aggiuntivi messi a disposizione per IIS7, raccolti sotto il nome di &lt;strong&gt;Dublin&lt;/strong&gt;, permettono di esporre workflow attraverso servizi e&amp;#xa0;di gestire e monitorare i workflow facilitando moltissimo la creazione di servizi duraturi nel tempo e scalabili.&lt;/p&gt;&lt;p&gt;Maggiori informazioni e le informazioni per il download sono disponibili nel nostro mini-sito dedicato al &lt;a href="http://netfx4.winfxitalia.com/"&gt;.NET Framework 4.0&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.0/" rel="tag"&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.0/" rel="tag"&gt;.NET Framework 4.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Windows_Communication_Foundation/" rel="tag"&gt;Windows Communication Foundation&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Windows_Workflow_Foundation/" rel="tag"&gt;Windows Workflow Foundation&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2498/.NET-Framework-4.0-Beta-1-Windows-Communication-Foundation.aspx"&gt;&lt;em&gt;.NET Framework 4.0 beta 1: Windows Communication Foundation&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, .NET Framework 3.0, .NET Framework 4.0, Windows Communication Foundation, Windows Workflow Foundation, .NET Framework</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2498/.NET-Framework-4.0-Beta-1-Windows-Communication-Foundation.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2498/.NET-Framework-4.0-Beta-1-Windows-Communication-Foundation.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2498.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2498</trackback:ping></item><item><title>Parallelizzare in Silverlight 2.0</title><link>http://blogs.aspitalia.com/ricciolo/post2487/Parallelizzare-Silverlight-2.0.aspx</link><pubDate>Tue, 21 Apr 2009 05:27:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2487" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Durante lo sviluppo di &lt;a href="http://lab.ricciolo.aspitalia.com/metadatadiffviewer/metadatadiffviewer.html"&gt;MetadataDiffViewer&lt;/a&gt; ho dovuto fare i conti con la grande quantità di informazioni da dover processare e dover trovare un modo di rendere l&amp;#39;interfaccia la più utilizzabile possibile. Per prima cosa ho optato per preparare una struttura di assembly/module/type/member tutta in lazy loading, in questo modo solo nell&amp;#39;espandere un assembly vengono caricati i moduli, solo espandendo un modulo vengono caricati i tipi ecc. &lt;b&gt;LINQ&lt;/b&gt; a questo scopo è fantastico perché lavorando con IEnumerable si può parserizzare, incrociare, ordinare, ma elaborare il tutto solo quando viene effettivamente consumato.&lt;/p&gt;
&lt;p&gt;Questo comporta però un difetto perché non mi consente di mostrare preventivamente quali assembly sono cambiati. Ho optato quindi per eseguire in un thread in background e ciclare per la struttura ad oggetti; appena trova un elemento cambiato, l&amp;#39;intero assembly è cambiato e perciò evito di proseguire. Questa operazione era comunque lunga e la cosa meno piacevole era vedere la cpu che lavorava solo al 50%, essendo un dual core.&lt;/p&gt;
&lt;p&gt;Mi son scritto quindi un piccolo extension method, specifico per la mia esigenza, per parallelizzare un&amp;#39;operazione basata su sorgenti LINQ. Il primo problema è determinare quanti core abbiamo a disposizione, ma non potendo accedere all&amp;#39;OS ho ripiegato sul fatto che il thread pool in &lt;b&gt;SL 2.0&lt;/b&gt; ha 250 thread per core e questo numero non si può cambiare. Perciò ho creato una semplice proprietà:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;private&lt;/span&gt; &lt;span style="color:#0000FF"&gt;const&lt;/span&gt; &lt;span style="color:#0000FF"&gt;int&lt;/span&gt; DefaultThreadsPerCpu = 250;

&lt;span style="color:#0000FF"&gt;public&lt;/span&gt; &lt;span style="color:#0000FF"&gt;static&lt;/span&gt; &lt;span style="color:#0000FF"&gt;int&lt;/span&gt; CpuNumber {
    &lt;span style="color:#0000FF"&gt;get&lt;/span&gt; {
        &lt;span style="color:#0000FF"&gt;int&lt;/span&gt; wt; &lt;span style="color:#0000FF"&gt;int&lt;/span&gt; cpt;
        ThreadPool.GetMaxThreads(&lt;span style="color:#0000FF"&gt;out&lt;/span&gt; wt, &lt;span style="color:#0000FF"&gt;out&lt;/span&gt; cpt);
        &lt;span style="color:#0000FF"&gt;return&lt;/span&gt; Math.Max(1, wt / DefaultThreadsPerCpu);
    }
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;L&amp;#39;extension method che ho poi definito accetta una sorgente dati sul quale ciclare e un delegate ad una funzione che elabora ogni item ed eventualmente restituisce un risultato:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;public&lt;/span&gt; &lt;span style="color:#0000FF"&gt;static&lt;/span&gt; IEnumerable&amp;lt;tresult&amp;gt; ForEach&amp;lt;IEnumerable&amp;lt;T&amp;gt;, TItem, TResult&amp;gt;
                                   (&lt;span style="color:#0000FF"&gt;this&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; source, Func&amp;lt;TItem, TResult&amp;gt; process)
{
{&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Per prima cosa ho ripartito la sorgente in n parti, quante sono le cpu, incrociando gli item. Ad esempio su due core al primo vanno l&amp;#39;item 1,3,5.., al secondo vanno 2,4,6.&lt;/p&gt;

&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;int&lt;/span&gt; cpuNumber = CpuNumber;

&lt;span style="color:#008000"&gt;// Elementi da processare per ogni cpu&lt;/span&gt;
IEnumerable&amp;lt;TItem&amp;gt;[] items = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; IEnumerable&amp;lt;TItem&amp;gt;[cpuNumber];
&lt;span style="color:#008000"&gt;// Semafori di notifica per ogni cpu&lt;/span&gt;
ManualResetEvent[] events = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; ManualResetEvent[cpuNumber];
&lt;span style="color:#008000"&gt;// Risultati ottenuti per ogni cpu&lt;/span&gt;
IList&amp;lt;TResult&amp;gt;[] results = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; IList&amp;lt;TResult&amp;gt;[cpuNumber];

&lt;span style="color:#0000FF"&gt;int&lt;/span&gt; itemsPerCpu = (&lt;span style="color:#0000FF"&gt;int&lt;/span&gt;)Math.Ceiling(source.Count() / (&lt;span style="color:#0000FF"&gt;double&lt;/span&gt;)cpuNumber);

&lt;span style="color:#0000FF"&gt;for&lt;/span&gt; (&lt;span style="color:#0000FF"&gt;int&lt;/span&gt; x = 0; x &amp;lt; items.Length; x++)
{
    items[x] = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; TItem[itemsPerCpu];
    &lt;span style="color:#0000FF"&gt;int&lt;/span&gt; cpu = x;
    &lt;span style="color:#008000"&gt;// Ripartizione incrociata&lt;/span&gt;
    items[x] = source.Where((item, index) =&amp;gt; (index + cpu) % cpuNumber == 0);
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;L&amp;#39;uso della variabile interna cpu che semplicemente ricopia x è fondamentale perché all&amp;#39;atto del consumo di items[] x sarebbe sempre all&amp;#39;ultimo valore. Usando LINQ occorre infatti ricordarsi che l&amp;#39;elaborazione avviene a posteriori, a meno non si chiami un ToList/ToArray.&lt;/p&gt;
&lt;p&gt;A questo punto avvio i thread e aspetto tramite un WaitHandle che questi abbiamo finito di lavorare:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;for&lt;/span&gt; (&lt;span style="color:#0000FF"&gt;int&lt;/span&gt; x = 0; x &amp;lt; items.Length; x++)
{
    &lt;span style="color:#008000"&gt;// Semaforo di notifica al thread che ha lanciato ForEach&lt;/span&gt;
    events[x] = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; ManualResetEvent(&lt;span style="color:#0000FF"&gt;false&lt;/span&gt;);
    results[x] = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; List&amp;lt;TResult&amp;gt;(itemsPerCpu);
    Thread t = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; Thread(&lt;span style="color:#0000FF"&gt;delegate&lt;/span&gt;(&lt;span style="color:#0000FF"&gt;object&lt;/span&gt; i)
    {
        &lt;span style="color:#0000FF"&gt;int&lt;/span&gt; index = (&lt;span style="color:#0000FF"&gt;int&lt;/span&gt;)i;

        &lt;span style="color:#0000FF"&gt;foreach&lt;/span&gt; (TItem item &lt;span style="color:#0000FF"&gt;in&lt;/span&gt; items[index])
            results[index].Add(process(item));

        events[index].Set();
    });
    t.Start(x);
}

WaitHandle.WaitAll(events);&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I risultati sono un List che poi vengono restituiti, in questo caso non nello stesso ordine della sorgente. Tutto questo per la mia esigenza, ma le variabili possono essere tante, in funzione della sorgente (può non essere possibile dividere il carico in quel modo), o del risultato (certi risultati dipendono dai risultati degli altri thread), ma è un inizio. L&amp;#39;uso poi è molto semplice:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;var r = from n &lt;span style="color:#0000FF"&gt;in&lt;/span&gt; Enumerable.Range(1, 1000)
     select &amp;quot;&lt;span style="color:#8B0000"&gt;Ciao &lt;/span&gt;&amp;quot; + n;
&lt;span style="color:#0000FF"&gt;int&lt;/span&gt; l = r.ForEach(s =&amp;gt; s.Length).Sum();&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/LINQ/" rel="tag"&gt;LINQ&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight/" rel="tag"&gt;Silverlight&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight_2.0/" rel="tag"&gt;Silverlight 2.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/XAML/" rel="tag"&gt;XAML&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2487/Parallelizzare-Silverlight-2.0.aspx"&gt;&lt;em&gt;Parallelizzare in Silverlight 2.0&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, .NET Framework 3.5, LINQ, Silverlight, Silverlight 2.0, XAML</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2487/Parallelizzare-Silverlight-2.0.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2487/Parallelizzare-Silverlight-2.0.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2487.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2487</trackback:ping></item><item><title>Silverlight: performance dell&amp;#39;isolated storage</title><link>http://blogs.aspitalia.com/ricciolo/post2484/Silverlight-Performance-Isolated-Storage.aspx</link><pubDate>Thu, 16 Apr 2009 17:03:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2484" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Durante lo sviluppo del &lt;a href="http://blogs.aspitalia.com/ricciolo/post2483/metadatadiffviewer-differenze-framework.aspx"&gt;MetadataDiffViewer&lt;/a&gt; ho dovuto ricorrere all'uso dell'Isolated Storage per salvare i metadati in locale e poterli prelevare da disco invece che da remoto. Ho notato però che le performance, rispetto allo scaricare da un webserver in locale, erano peggiori ed era imputabile a:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;la chiamata a&lt;strong&gt; IsolatedStorageFile.GetUserStoreForApplication/Site&lt;/strong&gt;: è molto costosa, aprendo lo storage una sola volta, dall'inizio alla fine ho guadagnato un 40% di performance; &lt;/li&gt;&lt;li&gt;la lettura dello stream attraverso &lt;strong&gt;IsolatedStorageFileStream&lt;/strong&gt;: è un più lenta rispetto ad uno stream in memoria nelle operazioni di accesso randomico. Questo è ovvio visto che va su disco, ma non pensavo così tanto. Precaricando il tutto in un MemoryStream e parserizzando poi l'XML con XDocument.Load in un'attività, ho guadagnato 3 secondi su 14 e non è poco. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Insomma, occhio a come lo usate.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/Silverlight/" rel="tag"&gt;Silverlight&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight_2.0/" rel="tag"&gt;Silverlight 2.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight_3.0/" rel="tag"&gt;Silverlight 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/XAML/" rel="tag"&gt;XAML&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2484/Silverlight-Performance-Isolated-Storage.aspx"&gt;&lt;em&gt;Silverlight: performance dell&amp;#39;isolated storage&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, Silverlight, Silverlight 2.0, Silverlight 3.0, XAML</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2484/Silverlight-Performance-Isolated-Storage.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2484/Silverlight-Performance-Isolated-Storage.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2484.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2484</trackback:ping></item><item><title>MetadataDiffViewer: differenze tra i framework</title><link>http://blogs.aspitalia.com/ricciolo/post2483/MetadataDiffViewer-Differenze-Framework.aspx</link><pubDate>Wed, 15 Apr 2009 16:56:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2483" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;&lt;a href="http://lab.ricciolo.aspitalia.com/metadatadiffviewer/metadatadiffviewer.html"&gt;MetadataDiffViewer&lt;/a&gt; è un'applicazione in &lt;strong&gt;Silverlight&lt;/strong&gt; che mostra le differenze in termini di assembly/module/type/member tra una versione del .NET Framework e l'altra. Semplicemente mostra alcune informazioni precalcolate per conoscere nel dettaglio cosa c'è di nuovo in una nuova versione.&lt;/p&gt; &lt;p&gt;Ecco uno screenshot:&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.aspitalia.com/img/ricciolo/metadatadiffviewerdifferenzetraiframewor_d943/metadatadiffviewer_4.jpg"&gt;&lt;img title="metadatadiffviewer" border="0" alt="metadatadiffviewer" src="http://blogs.aspitalia.com/img/ricciolo/metadatadiffviewerdifferenzetraiframewor_d943/metadatadiffviewer_thumb_1.jpg" width="340" height="295" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Lo potete provare &lt;a href="http://lab.ricciolo.aspitalia.com/metadatadiffviewer/metadatadiffviewer.html"&gt;qua&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Non so voi, ma mi dà fastidio essermi perso un nuovo membro. Con questo tool non ci sono più scuse :-)&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Come funziona?&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Ho innanzitutto creato un addin per &lt;strong&gt;Reflector&lt;/strong&gt; così da poter esportare i metadati pubblici degli assembly. La reflection classica non permette di caricare più versione del framework e in un'ottica continua nel tempo ho deciso di esportare i metadati e tenerli sempre pronti. Una console application poi li compara e crea un file di differenze. I metadati e le differenze sono file XML di discreta dimensione perciò, per non riscaricare tutte le informazioni ogni volta, ho deciso di salvare le informazioni nell'isolated storage. Per tenersi il tutto servono circa 60MB (tranquilli, sono zippati quando si scaricano).&lt;/p&gt; &lt;p&gt;I framework comparati che sono a disposizione sono:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Silverlight 2.0 -&amp;gt; Silverlight 3.0 &lt;/li&gt; &lt;li&gt;.NET Framework 1.1 -&amp;gt; .NET Framework 2.0 &lt;/li&gt; &lt;li&gt;.NET Framework 2.0 -&amp;gt; .NET Framework 3.5 &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Se avete problemi o consigli, &lt;a href="mailto:cristian@aspitalia.com"&gt;scrivetemi&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_2.0/" rel="tag"&gt;.NET Framework 2.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.0/" rel="tag"&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight/" rel="tag"&gt;Silverlight&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight_2.0/" rel="tag"&gt;Silverlight 2.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight_3.0/" rel="tag"&gt;Silverlight 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/XAML/" rel="tag"&gt;XAML&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2483/MetadataDiffViewer-Differenze-Framework.aspx"&gt;&lt;em&gt;MetadataDiffViewer: differenze tra i framework&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, .NET Framework, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5, Silverlight, Silverlight 2.0, Silverlight 3.0, XAML</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2483/MetadataDiffViewer-Differenze-Framework.aspx</guid><slash:comments>5</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2483/MetadataDiffViewer-Differenze-Framework.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2483.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2483</trackback:ping></item><item><title>Documentazione MSDN e versioni del .NET Framework</title><link>http://blogs.aspitalia.com/ricciolo/post2482/Documentazione-MSDN-Versioni-.NET-Framework.aspx</link><pubDate>Wed, 15 Apr 2009 13:23:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2482" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;In questo post qualcosa di poco tecnologico, ma che mi segno per me e magari anche voi, per trovare velocemente la documentazione delle classi. Le versioni del framework sono infatti ormai tante: .NET Framework 1.0 - 1.1 - 2.0 - 3.5 e Silverlight 2.0 - 3.0.&lt;/p&gt;&lt;p&gt;Cercando nei motori di ricerca per esempio system.string probabilmente troveremo il link a:&lt;/p&gt;&lt;p&gt;&lt;a title="http://msdn.microsoft.com/en-us/library/system.string.aspx" href="http://msdn.microsoft.com/en-us/library/system.string.aspx"&gt;http://msdn.microsoft.com/en-us/library/system.string.aspx&lt;/a&gt;&lt;/p&gt;&lt;p&gt;che ci porta alla documentazione riferita alla versione attuale: la 3.5.&lt;/p&gt;&lt;p&gt;Mettendo tra parentesi dopo system.string la versione possiamo però distinguere e forzatamente guardare uno specifico framework. Per Silverlight 3.0 per esempio è:&lt;/p&gt;&lt;p&gt;&lt;a title="http://msdn.microsoft.com/en-us/library/system.string(vs.96).aspx" href="http://msdn.microsoft.com/en-us/library/system.string(vs.96).aspx"&gt;http://msdn.microsoft.com/en-us/library/system.string(vs.96).aspx&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Ecco un riassunto delle versioni:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;vs.71: 1.1 &lt;/li&gt;&lt;li&gt;vs.80: 2.0 &lt;/li&gt;&lt;li&gt;vs.85: 3.0 &lt;/li&gt;&lt;li&gt;vs.90: 3.5 &lt;/li&gt;&lt;li&gt;vs.95: SL 2.0 &lt;/li&gt;&lt;li&gt;vs.96: SL 3.0 &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_2.0/" rel="tag"&gt;.NET Framework 2.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.0/" rel="tag"&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight/" rel="tag"&gt;Silverlight&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight_2.0/" rel="tag"&gt;Silverlight 2.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight_3.0/" rel="tag"&gt;Silverlight 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/XAML/" rel="tag"&gt;XAML&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2482/Documentazione-MSDN-Versioni-.NET-Framework.aspx"&gt;&lt;em&gt;Documentazione MSDN e versioni del .NET Framework&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, .NET Framework, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5, Silverlight, Silverlight 2.0, Silverlight 3.0, XAML</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2482/Documentazione-MSDN-Versioni-.NET-Framework.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2482/Documentazione-MSDN-Versioni-.NET-Framework.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2482.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2482</trackback:ping></item><item><title>Curiosit&amp;#224; sui Thread</title><link>http://blogs.aspitalia.com/ricciolo/post2187/Curiosita-Thread.aspx</link><pubDate>Sun, 16 Dec 2007 22:45:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2187" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;In questi giorni grazie ad un esigenza di &lt;a onclick="function anonymous()
{
function anonymous()
{
function anonymous()
{
blankUrl(this.href); return false;
}
}
}" href="http://blogs.devleap.com/rob/"&gt;Rob&lt;/a&gt; e &lt;a onclick="function anonymous()
{
function anonymous()
{
function anonymous()
{
blankUrl(this.href); return false;
}
}
}" href="http://blogs.devleap.com/paolo/"&gt;Paolo&lt;/a&gt;, ho voluto approfondire un aspetto di cui ero già a conoscienza, ma del quale non avevo mai fatto test. &lt;br /&gt;Come sapete, un campo dichiarato in una classe può teoricamente subire contemporaneamente l'accesso da più &lt;strong&gt;thread&lt;/strong&gt; e spesso per rendere la classe thread-safe si ricorrono a tecniche di sincronizzazione per evitare che più thread cambino contemporanemante il campo. Non è detto infatti che una singola istruzione di assegnazione sia una singola istruzione di CPU e questo può portare ad inaspettati risultati. Questo problema si fa inoltre più frequente se si dichiara static (o shared in VB) il campo, condividendo il valore del membro per l'intero AppDomain.&lt;/p&gt;&lt;p&gt;A volte però, si vuole rendere l'istanza del campo accessible da chiunque purché dal medesimo thread, togliendo quindi il problema dell'accesso concorrente. L'attributo &lt;strong&gt;ThreadStatic&lt;/strong&gt; permette di marcare un campo e di avere questo comportamento:&lt;/p&gt;&lt;p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;[ThreadStatic] &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;private static object threadState;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;Questa tecnica viene sfruttata per esempio dall'oggetto &lt;strong&gt;Transaction&lt;/strong&gt; (System.Transactions) per mantenere l'oggetto rappresentante la transazione corrente cosicchè qualsiasi sotto chiamata possa accedere alla transazione corrente semplicemente chiamando Transaction.Current, il tutto isolato per thread (la transazione infatti non è visibile in altri thread, ma ne viene creata un'altra). Lo stesso comportamento, seppure meno comodo, si può ottenere usando &lt;strong&gt;Thread.AllocateNamedDataSlot&lt;/strong&gt;, Thread.SetData e Thread.GetData che permettono di allocare per nome uno spazio, di impostarlo e di leggerlo, dove inserire un riferimento ad un oggetto.&lt;/p&gt;&lt;p&gt;La problematica di questo approccio è che nel caso in cui da un thread ne avviamo un altro e si vuole portare con se questi valori &amp;quot;speciali&amp;quot;, occorre passarseli tramite argomenti o classi d'appoggio per poi essere copiati sul nuovo thread. Inoltre nel caso del &lt;strong&gt;ThreadPool&lt;/strong&gt;, quell'insieme di thread già pronti all'uso, utilizzati quando si chiama la Begin*** di un delegate o si usa &lt;strong&gt;ThreadPool.QueueUserWorkItem&lt;/strong&gt;, il campo statico risulta visibile alle operazioni che verranno prese in carico dal medesimo thread e mai rilasciato (si pensi al Dispose dell'oggetto) se non sovrascritto o impostato a null (il ThreadPool nel .NET 2.0 è composta da 25 Thread per CPU e di 500 IO Thread per CPU, in ASP.NET 2.0 sono 100/100, nel.NET 3.5 sono diventanti 250/500, mentre in ASP.NET 3.5 nella modalità AutoConfig sono rimasti invariati).&lt;/p&gt;&lt;p&gt;Per risolvere questo problema viene in aiuto la classe &lt;strong&gt;CallContext&lt;/strong&gt; (System.Runtime.Remoting.Messaging) con i metodi &lt;strong&gt;LogicalGetData&lt;/strong&gt; e &lt;strong&gt;LogicalSetData&lt;/strong&gt; per leggere e impostare in base ad una chiave il riferimento ad un oggetto. Il comportamento è simile a ThreadStatic, ma questi valori sono relativi al contesto in cui sono stati impostati. Per capire meglio ho creato questa classe:&lt;/p&gt;&lt;p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;public class MyObject : Component &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;{ &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;private readonly string _name; public MyObject(string name) &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;{ &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _name = name; &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;} protected override void Dispose(bool disposing) &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;{&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.Dispose(disposing); &amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;amp;quot;Disposed {0}&amp;amp;quot;, _name); &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;} public override string ToString() &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;{&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _name; &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;} &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;E' una semplice classe che implementa &lt;strong&gt;IDisposable&lt;/strong&gt; così da sapere quando l'oggetto, identificato con un nome, viene distrutto. Poi ho creato una ConsoleApplication che esegue su un thread del pool il controllo di un campo marcato con ThreadStatic, lo valorizza se è nullo e ne stampa il valore. La stessa operazione viene effettuata usando CallContext. Inoltre, attendo la fine dell'esecuzione per assicurarmi che le altre successive operazioni vengono effettuate nuovamente sul medesimo thread ed utilizzo &lt;strong&gt;GC.Collect&lt;/strong&gt; per assicurarmi che gli oggetti, non più in uso, vengano distrutti (mi raccomando, in vere applicazioni non si deve chiamare se non in rare eccezioni):&lt;/p&gt;&lt;p /&gt;&lt;p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;class Program &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;{ [ThreadStatic] &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;private static object threadState; static void Main(string[] args) &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;{&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Metodo da invocare su un Thread del pool&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaitCallback wc = DoWork; &amp;nbsp;&amp;nbsp;&amp;nbsp; for (int x = 0; x &amp;amp;lt; 3; x++)&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Invoco e attendo che finisca&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wc.BeginInvoke(null, EndWork, wc).AsyncWaitHandle.WaitOne(); &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Forzo la liberazione degli oggetti&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GC.Collect();&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GC.WaitForPendingFinalizers();&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &amp;nbsp;&amp;nbsp;&amp;nbsp; // Avvio l&amp;#39;operazione su un nuovo Thread&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Thread t = new Thread(DoWork);&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; t.Start();&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; t.Join(); &amp;nbsp;&amp;nbsp;&amp;nbsp; // Forzo la liberazione degli oggetti&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GC.Collect();&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GC.WaitForPendingFinalizers(); &amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Read(); &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;} private static void EndWork(IAsyncResult ar) &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;{&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((WaitCallback)ar.AsyncState).EndInvoke(ar); &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;} const string DataKey = &amp;amp;quot;test&amp;amp;quot;; static void DoWork(object state) &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;{&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;amp;quot;-----------------&amp;amp;quot;);&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;amp;quot;Thread {0}&amp;amp;quot;, Thread.CurrentThread.ManagedThreadId); &amp;nbsp;&amp;nbsp;&amp;nbsp; object t = CallContext.LogicalGetData(DataKey);&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (t == null)&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; t = new MyObject(&amp;amp;quot;LogicalData&amp;amp;quot;);&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;amp;quot;LogicalData set&amp;amp;quot;);&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CallContext.LogicalSetData(DataKey, t);&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;amp;quot;LogicalData: {0}&amp;amp;quot;, t); &amp;nbsp;&amp;nbsp;&amp;nbsp; t = threadState;&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (t == null)&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; t = new MyObject(&amp;amp;quot;DataThread&amp;amp;quot;);&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; threadState = t;&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;amp;quot;DataThread set&amp;amp;quot;);&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&amp;amp;quot;DataThread: {0}&amp;amp;quot;, t);&amp;nbsp;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;Se lo si esegue, il risultato è il seguente:&lt;/p&gt;&lt;p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;----------------- &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;Thread 6 &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;LogicalData set &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;DataThread set &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;----------------- &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;Thread 6 &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;LogicalData set &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;DataThread: DataThread &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;Disposed LogicalData &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;----------------- &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;Thread 6 &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;LogicalData set &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;DataThread: DataThread &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;Disposed LogicalData &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;Disposed LogicalData &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;----------------- &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;Thread 11 &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;LogicalData set &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;DataThread set &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;Disposed DataThread&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;Come si vede, alla prima esecuzione di DoWork, entrambi i modi di memorizzare MyObject impostano il valore. Alla seconda esecuzione CallContext è di nuovo vuoto e va rivalorizzato, mentre threadState contiene il valore impostato sulla prima esecuzione. Lo stesso avviene anche alla terza esecuzione. E' interessante notare che l'oggetto impostato con CallContext viene effettivamente rilasciato e quindi ucciso dal GC solo all'avviarsi della nuova operazione sul medesimo thread (infatti il primo GC.Collect non ha sortito nessun effetto). Poiché i thread del pool non muoiono mai, DataThread non viene mai eliminato, ad eccezione di quello impostato nel Thread creato manualmente (l'esecuzione è finita e quindi il thread è inutilizzabile). &lt;br /&gt;Tutto questo meccanismo è gestito dalla classe &lt;strong&gt;ExecutionContext&lt;/strong&gt; (System.Threading) che è in grado di catturare, mettere a disposizione o di togliere il contesto e tutti valori ad esso associati. Quando si chiama ThreadPool.QueueUserWorkItem o il Begin*** di un metodo, viene chiamato ExecutionContext.Capture per catturare il contesto e tenerselo pronto quando il thread prende in consegna il delegate da eseguire, ripristinando quindi il contesto chiamando il metodo Run. Se avete mai dovuto creare un vostro ThreadPool, tipo &lt;a onclick="function anonymous()
{
function anonymous()
{
function anonymous()
{
blankUrl(this.href); return false;
}
}
}" href="http://msdn.microsoft.com/msdnmag/issues/06/03/netmatters/"&gt;questo&lt;/a&gt;, avrete sicuramente avuto a che fare con questa classe. Il bello di questo meccanismo è che se usiamo CallContext per mantenere dei valori ed invochiamo delegate asincroni o creiamo thread, automaticamente il contesto viene passato sull'altro thread condividendolo per la durata dell'operazione. Se nell'esempio precedente quindi si imposta prima di qualsiasi accodamento, l'istruzione CallContext.LogicalSetData(DataKey, new MyObject(&amp;quot;test&amp;quot;)); si ottiene a console:&lt;/p&gt;&lt;p /&gt;&lt;p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;Thread 6 &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;LogicalData: test &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;DataThread set &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;----------------- &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;Thread 6 &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;LogicalData: test &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;DataThread: DataThread &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;----------------- &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;Thread 6 &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;LogicalData: test &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;DataThread: DataThread &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;----------------- &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;Thread 11 &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;LogicalData: test &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;DataThread set &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;br&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;Disposed DataThread&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;Si noti che LogicalData su tutti i thread è già impostato.&lt;/p&gt;&lt;p&gt;Un'ultimo aspetto riguarda ASP.NET che utilizza anch'esso CallContext.HostContext ogni qualvolta si interroga HttpContext.Current, ma se si usano pagine asincrone con task ecc, i metodi asincroni non dispongono del contesto web e HttpContext.Current ritorna null. Diversamente usando CallContext.LogicalSetData si ha a disposizione l'oggetto anche sui task asincroni ed è quindi l'ideale se dovete mantenere DataContext (LINQ) o Session (NHibernate).&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2187/Curiosita-Thread.aspx"&gt;&lt;em&gt;Curiosit&amp;#224; sui Thread&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2187/Curiosita-Thread.aspx</guid><slash:comments>4</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2187/Curiosita-Thread.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2187.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2187</trackback:ping></item><item><title>Perch&amp;#233; non usate lo statement using?</title><link>http://blogs.aspitalia.com/ricciolo/post2177/Usate-Statement-Using.aspx</link><pubDate>Thu, 06 Dec 2007 11:38:32 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2177" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Me lo chiedo perché la vedo raramente usata nei forum e nel codice che mi capita di guardare e mi domando il perché, visto che è così comoda da usare. Beh il mio consiglio è: qualsiasi oggetto create, se implementa &lt;strong&gt;IDisposable&lt;/strong&gt;, usate sempre la using. &lt;br /&gt;Per i seguenti motivi:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Occorre sempre chiudere risorse unmanaged in modo esplicito e il prima possibile. Se si demanda il lavoro al &lt;strong&gt;Garbage Collector&lt;/strong&gt; il Dispose verrà effettuato sfruttando la &lt;strong&gt;Finalize&lt;/strong&gt; e l'oggetto resterà nell'heap per un giro di GC in più e rischiamo inoltre che l'oggetto diventi più forte come generation e non venga più rimosso; &lt;/li&gt; &lt;li&gt;Anche se l'oggetto non fa uso risorse unmanaged, la Dispose va chiamata lo stesso. Primo perché non possiamo mai sapere se in una futura versione l'oggetto utilizzerà tali risorse e secondo perché chiamando Dispose, se la classe è scritta bene, viene chiamato &lt;strong&gt;GC.SuppressFinalize&lt;/strong&gt;(this) così da togliere l'oggetto dalla finalization list, il GC lo rimuoverà dall'heap e il problema indicato nel primo punto non si verificherà. &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Se scriviamo delle nostre classi che fanno uso di risorse unmanaged o di classi che a loro volta ne fanno uso, vi consiglio di ereditare da &lt;strong&gt;System.ComponentModel.Component&lt;/strong&gt;. Implementa già il pattern Dispose, con l'interfaccia IDisposable, il metodo Finalize e mettendo a disposizione un metodo virtuale Dispose(bool disposing). Una tipica classe è così:&lt;/p&gt; &lt;code&gt;public class MiaClasse : System.ComponentModel.Component &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private bool disposed; &lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void MioMetodo() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (disposed) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new ObjectDisposedException(base.GetType().Name); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected override void Dispose(bool disposing) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (disposing) { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; risorsaunmanaged.Dispose(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; risorsaunmanaged = null; &lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.disposed = true; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.Dispose(disposing); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;}&lt;/code&gt; &lt;p&gt;L'uso della variabile disposed è &amp;quot;facoltaltiva&amp;quot;, ma utile se vogliamo lanciare un eccezione nel caso qualcuno chiami un nostro metodo quando ne ha già chiamato il Dispose. &lt;br /&gt;Quindi insomma, usiamo la using che non vi costa e scriviamo le classi nel modo giusto ;-)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2177/Usate-Statement-Using.aspx"&gt;&lt;em&gt;Perch&amp;amp;eacute; non usate lo statement using?&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, .NET Framework</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2177/Usate-Statement-Using.aspx</guid><slash:comments>15</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2177/Usate-Statement-Using.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2177.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2177</trackback:ping></item><item><title>Interoperabilit&amp;#224; .NET con C++ CLI</title><link>http://blogs.aspitalia.com/ricciolo/post2167/Interoperabilita-.NET-C-CLI.aspx</link><pubDate>Mon, 26 Nov 2007 22:26:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2167" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;In quest'ultimo periodo mi sono addentrato in un mondo che ho sempre ammirato, ma che non ho mai avuto il coraggio di provare: il &lt;strong&gt;C++ CLI&lt;/strong&gt;. Ammirato perché già non ho mai usato C++, figuriamoci un linguaggio più evoluto. Per chi non lo sapesse, infatti, C++ CLI è un linguaggio standard ECMA evoluzione delle Managed Extensions C++ e quindi di C++ che permette di mettere in comunicazione il mondo managed .NET con quello unmanaged.&lt;/p&gt;&lt;p&gt;Questo vuol dire che è possibile scrivere DLL che contengano sia codice nativo che lavori con qualsiasi API, sia codice managed che faccia uso poi di classi native. Oltre a ciò è possibile ottenere il codice di interop in automatico scrivendo direttamente da codice managed chiamate a tipi o funzioni native. Così facendo si riduce al minimo il marshaling dei tipi e C++ CLI diventa l'ideale per scrivere classi che  permettano di beneficiare dei pregi dei due mondi.&lt;br /&gt;Se avete avuto modo di usare la classe &lt;strong&gt;Marshal&lt;/strong&gt; di System.Runtime.InteropServices sapete delle fatiche che si devono compiere per le strutture ecc e apprezzerete sicuramente questo nuovo strumento.&lt;/p&gt;&lt;p&gt;Beh insomma dopo un po' che ci sto lavorando devo dire che è ganzissimo. Ti senti come &lt;a href="http://it.wikipedia.org/wiki/Peter_Petrelli"&gt;Peter Petrelli&lt;/a&gt; quando si ritrova tutti quei poteri. Come il personaggio nel senso che come lui non sono capace di usarli e mi fermo fra elementari ostacoli come conversione dei tipi, utilizzo delle librerie e puntatori. Pian piano però sto prendendo possesso di questi poteri, quindi più avanti vi illustrerò cosa sono riuscito a fare.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_2.0/" rel="tag"&gt;.NET Framework 2.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.0/" rel="tag"&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2167/Interoperabilita-.NET-C-CLI.aspx"&gt;&lt;em&gt;Interoperabilit&amp;#224; .NET con C++ CLI&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, .NET Framework, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2167/Interoperabilita-.NET-C-CLI.aspx</guid><slash:comments>1</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2167/Interoperabilita-.NET-C-CLI.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2167.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2167</trackback:ping></item><item><title>Alternativa ai captcha normali</title><link>http://blogs.aspitalia.com/ricciolo/post1371/Alternativa-Captcha-Normali.aspx</link><pubDate>Fri, 02 Dec 2005 12:53:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=1371" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Qualche tempo fa Matteo parlò in un suo &lt;a href="http://blogs.aspitalia.com/matteo/post1275/CAPTCHAFermaSpam.aspx"&gt;post&lt;/a&gt; dei sistemi anti spam che richiedono capacità umane per vincere i programmi automatici di spam.&lt;/p&gt;&lt;p&gt;Beh visto che molti algoritmi riescono ad aggirare anche queste protezioni mi son chiesto: cos'è che proprio un software non sa fare?&lt;br /&gt;Ho pensato quindi di popolare un database con delle parole, oggetti singolari e semplici e di prelevare una di queste randomicamente.&lt;br /&gt;Sfruttando poi il motore di google images prelevo le prime cinque immagini e chiedo all'utente di indicare l'oggetto che vede e intuisce. Considerando che le prime immagini che google propone sono spesso attinenti all'oggetto in questione, che la parola è in italiano e singolare quasi sempre la si può indovinare.&lt;/p&gt;&lt;p&gt;Lo potete &lt;a href="http://www.xmlroot.it/ricciolo/imagecaptcha" target="_blank"&gt;provare qua&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Cosa ne pensate? Cavolata? Forse sì, ma la strada secondo me non è sbagliata. Voglio vedere quale algoritmo possa equiparare l'intelligenza umana messa in campo in questo caso. Ovvio che il database è limitato all'italiano, ma si può benissimo nazionalizzare per tutte le lingue, visto che google non soffre di questi problemi.&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post1371/Alternativa-Captcha-Normali.aspx"&gt;&lt;em&gt;Alternativa ai captcha normali&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post1371/Alternativa-Captcha-Normali.aspx</guid><slash:comments>8</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post1371/Alternativa-Captcha-Normali.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS1371.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=1371</trackback:ping></item><item><title>Compilare per .NET 1.x da Visual Studio 2005?</title><link>http://blogs.aspitalia.com/ricciolo/post1343/Compilare-.NET-1.x-Visual-Studio-2005.aspx</link><pubDate>Wed, 09 Nov 2005 17:47:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=1343" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;A quanto pare la cosa è fattibile. Grazie al fatto che Visual Studio 2005 utilizza msbuild (console per la compilazione compreso nel Framework) è possibile con un nuovo file di building compilare per la versione .NET 1.x.&lt;/p&gt;&lt;p&gt;Le istruzioni le trovate &lt;a href="http://blogs.msdn.com/jomo_fisher/archive/2005/04/22/410903.aspx" target="_blank"&gt;qua&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Non ho ancora provato, ma credo sia una cosa che interessi in molti.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/Visual_Studio/" rel="tag"&gt;Visual Studio&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post1343/Compilare-.NET-1.x-Visual-Studio-2005.aspx"&gt;&lt;em&gt;Compilare per .NET 1.x da Visual Studio 2005?&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, Visual Studio</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post1343/Compilare-.NET-1.x-Visual-Studio-2005.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post1343/Compilare-.NET-1.x-Visual-Studio-2005.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS1343.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=1343</trackback:ping></item><item><title>Libreria per XML</title><link>http://blogs.aspitalia.com/ricciolo/post1194/Libreria-XML.aspx</link><pubDate>Thu, 08 Sep 2005 17:37:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=1194" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Il supporto a XML nel Framework.NET è notevole, ma a volte non abbastanza. Per questo vi segnalo questa libreria aggiuntiva &amp;quot;&lt;a href="http://sourceforge.net/projects/mvp-xml" target="_blank"&gt;MVP XML&lt;/a&gt;&amp;quot; che si sta dimostrando per i miei usi molto utile.&lt;br /&gt;Mi è stata suggerita per necessità dal mio &lt;a href="http://blogs.devleap.com/paolo/" target="_blank"&gt;maestro alias Mr. Xml&lt;/a&gt; ed è sviluppata da un &lt;a href="http://weblogs.asp.net/cazzu/"&gt;MVP&lt;/a&gt; che a parte il nome ambiguo sembra essere molto in gamba.&lt;/p&gt;&lt;p&gt;La libreria ha alcune classi molto utili della quale trovate una spiegazione completa &lt;a href="http://weblogs.asp.net/cazzu/archive/2004/05/15/132532.aspx" target="_blank"&gt;qua&lt;/a&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;DynamiContext: utilissimo, vi dà la possibilità di inserire variabili in query XPath:&lt;/li&gt;&lt;li&gt;IndexingXPathNavigator: XPathNavigator che ottimizza le query XPath in funzioni di chiavi specificabili&lt;/li&gt;&lt;li&gt;XPathNavigatorReader: eredita da XmlTextReader e accetta come costruttore un XPathNavigator. Utilize se per esempio volete caricare un XmlDocument da un XPathDocument&lt;/li&gt;&lt;li&gt;XPathIteratorReader: come sopra ma accetta un XPathNodeIterator&lt;/li&gt;&lt;li&gt;XmlNodeNavigator: si tratta di un XPathNavigator che accetta come costruttore un XmlNode. Implementa IHasXmlNode e il vantaggio sta nel fatto che a seguito di select o navigazione è sempre possibile risalire all'XmlNode originale&lt;/li&gt;&lt;li&gt;SubtreeXPathNavigator: un XPathNavigator che accetta un XPathNavigator, ma ha il vantaggio di poter rappresentare un documento frammentario. E' utile quando si fanno trasformazioni XSLT. Passare infatti un iterator ad una trasformazione rende visibile l'intero documento ad essa e non magari solo una parte preselezionata.&lt;/li&gt;&lt;li&gt;XmlFirstUpperReader and XmlFirstLowerWriter: si trattano di un XmlTextReader e di un XmlTextWriter che permottono di caricare o salvare tag e attributi con lettera maiuscola o minuscolo. L'esigenza nasce dal fatto che negli schema xsd e in generale in xml si preferisce usare la nomenclatura pascalCase mentre in .NET si utilizza la PascalCase. Essendo xml case sensitive spesso porta alla rinuncia della nomenclatura PascalCase. Con queste due classi in pratica si fa ignorare il casing dei nomi.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/XML/" rel="tag"&gt;XML&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post1194/Libreria-XML.aspx"&gt;&lt;em&gt;Libreria per XML&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, XML</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post1194/Libreria-XML.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post1194/Libreria-XML.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS1194.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=1194</trackback:ping></item><item><title>Persistere automaticamenti i controlli con il ViewState (parte 1&amp;#176;)</title><link>http://blogs.aspitalia.com/ricciolo/post1190/Persistere-Automaticamenti-Controlli-ViewState-Parte-1.aspx</link><pubDate>Wed, 07 Sep 2005 17:49:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=1190" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Prima di buttarmi nel futuro raccontadovi ciò che seguirò a PDC voglio restare nel presente parlandovi di un problema comune.&lt;br /&gt;Capita spesso di dover creare controlli a runtime in base alle informazioni date dall'utente, da una fonte db o xml e la prima volta che l'abbiamo fatto credo che tutti (almeno io, cascato in pieno) ci siamo trovati di fronte a seguito di un postback alla misteriosa scomparsa di essi.&lt;br /&gt;A dir la verità i controlli sono sempre creati a runtime, anche quelli presenti nei file aspx e ascx, solo che il codice è persistito nei files temporanei e viene rieseguito ad ogni richiesta della pagina.&lt;br /&gt;Dobbiamo infatti ricordarci che ogni richiesta è soddisfatta con una nuova istanza della nostra classe Page, di conseguenza i controlli e tutto ciò che è stato fatto viene perso.&lt;br /&gt;La soluzione che di solito adotto consiste nel memorizzare nel ViewState le informazioni minime indispensabili per ricreare almeno lo stesso albero di controlli presente alla richiesta precente.&lt;br /&gt;Per esempio se dal db prelevo 10 records che mi indicano di creare 10 TextBox con un certo colore e dimensione, mi limiterò a memorizzare solo il numero 10 nel ViewState. Questo perché al postback della pagina il numero delle TextBox è sufficiente per creare la stessa lista di controlli. Per il resto ci penserà il ViewState di ogni controllo che di default memorizza tutte le sue proprietà di colore, style e dimensione.&lt;br /&gt;L'ho probabilmente già detto, ma lo ripeto. Questo codice:&lt;/p&gt;&lt;p&gt;&lt;code&gt;TextBox t1 = new TextBox();&lt;br /&gt;t1.ForeColor = Color.Red;&lt;br /&gt;this.Controls.Add(t1);&lt;/code&gt;&lt;/p&gt;&lt;p&gt;è diverso da:&lt;/p&gt;&lt;p&gt;&lt;code&gt;TextBox t1 = new TextBox();&lt;br /&gt;this.Controls.Add(t1);&lt;br /&gt;t1.ForeColor = Color.Red;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Il primo infatti non persiste nel ViewState la proprietà ForeColor e potrebbe portare a risultati inattesi. Viceversa potrebbe essere utile, per ottimizzare il ViewState solo in certe proprietà, il primo codice.&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post1190/Persistere-Automaticamenti-Controlli-ViewState-Parte-1.aspx"&gt;&lt;em&gt;Persistere automaticamenti i controlli con il ViewState (parte 1&amp;#176;)&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post1190/Persistere-Automaticamenti-Controlli-ViewState-Parte-1.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post1190/Persistere-Automaticamenti-Controlli-ViewState-Parte-1.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS1190.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=1190</trackback:ping></item><item><title>AJAX: tocca a me...</title><link>http://blogs.aspitalia.com/ricciolo/post1171/AJAX-Tocca-Me.aspx</link><pubDate>Sat, 20 Aug 2005 14:11:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=1171" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Mi ero promesso di non parlarne, ma non riesco a resistere alla tentazione ora che &lt;a href="http://blogs.aspitalia.com/daniele/"&gt;Boss Hogg&lt;/a&gt; mi ha &lt;a href="http://blogs.aspitalia.com/daniele/post1170/AJAXLavaFondo2.aspx"&gt;chiamato&lt;/a&gt; in causa. E' buffo come dell'argomento ne parlano soprattutto chi vuole frenare la moda del momento: AJAX.&lt;/p&gt;&lt;p&gt;Sebbene abbia realizzato le &lt;a href="http://lab.aspitalia.com/19/RiccioloClientPages10136495.aspx"&gt;ClientPages&lt;/a&gt; che appunto sfruttano XmlHttp non vuol dire che ne condivido l'uso spropositato. Mi era passato per la testa di realizzare controlli più complessi come DataGrid che si popolano o notificatori di operazioni senza effettuare postback, ma poi ho rinunciato perché l'ho ritenuto troppo pericoloso.&lt;br /&gt;Purtroppo però qualcosa di simile sarà implementato in &lt;a href="http://weblogs.asp.net/scottgu/archive/2005/06/28/416185.aspx" target="_blank"&gt;Atlas&lt;/a&gt;. Dico purtroppo perché già oggi spesso trovo utenti che fanno confunsione tra client e server, tra JavaScript e .NET e AJAX potrà aumentare tutto questo disordine.&lt;br /&gt;I commenti che si leggono non sono contro l'adozione da parte di Microsoft di questa tecnologia, ma semplicemente vogliono istruire noi tutti nell'usarli con moderazione. Semplicemente la mia idea per far si che ciò avvenga è quella di progettare i siti come si è sempre fatto e considerare DropDown che si popolano al volo, operazioni di Drag&amp;amp;Drop ecc solo qualcosa di optional, di più e solo se supportato dal browser. Così non mineremo l'usabilità e l'accessibilità del sito.&lt;br /&gt;Se poi l'esigenza si fa più forte allora è meglio pensare a qualcosa di più adeguato alla situazione come gli SmartClient: applicazioni WinForms connesse ad Internet che sanno lavorare in modalità Online/Offline.&lt;/p&gt;&lt;p&gt;Ritornando ad Atlas mi è venuto in mente solo ora che l'anno scorso &lt;a href="http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=a12e2335-2c20-497a-bc5a-a7783df10fdf"&gt;proposi&lt;/a&gt; di usare Ajax sfruttando l'adaptive rendering in base alla mie esperienza con le ClientPages.&lt;br /&gt;Spero comunque in una implementazione ben fatta, magari con pochi controlli e che soprattutto sincronizzino il ViewState ad ogni ClientCallback così da poter mixare postbacks con clientcallbacks.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/AJAX/" rel="tag"&gt;AJAX&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post1171/AJAX-Tocca-Me.aspx"&gt;&lt;em&gt;AJAX: tocca a me...&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2013 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, AJAX</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post1171/AJAX-Tocca-Me.aspx</guid><slash:comments>2</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post1171/AJAX-Tocca-Me.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS1171.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=1171</trackback:ping></item></channel></rss>