Dynamic Language Runtime .NET 4.0(Beta 2)

by Marco 20. gennaio 2010 14.13

Nel framework 4.0 è stato aggiunto un insieme di classi che ci permettono di rendere il nostro codice e il .NET framework in generale “dinamico”. Cosa intendo per “dinamico”? Prendiamo ad esempio un semplice frammento di codice C#:


MyClass c = new MyClass();
c.Foo();

dal momento che questo codice compila possiamo affermare con sicurezza che la classe MyClass ha un metodo Foo() che viene invocato sull’istanza c. Questa assunzione la fa anche il compilatore che verifica a compile-time che quello che il nostro amato e “statico” C# esprime sia corretto. Quando dico statico intendo il fatto che se utilizziamo un linguaggio “statico”(come C# e VB) dobbiamo specificare il tipo dell’oggetto(MyClass) a design-time, ovvero indico con precisione al compilatore quale sarà il codice del metodo Foo() che dovrà essere eseguito a runtime. Nel nostro esempio dovrò eseguire il metodo Foo() definito nella classe MyClass sull’istanza riferita da c.

Il sistema dei tipi del .NET Framework è fatto da tipi “statici” nel senso che noi dichiariamo al momento della scrittura del codice il “tipo” che vogliamo utilizzare e il compilatore al momento della compilazione controlla che quello che abbiamo scritto sia “staticamente” corretto(che il tipo esista e abbia i vari membri che vogliamo utilizzare).

Con .NET 4.0 possiamo rendere il semplice frammento di codice dinamico, esempio(C#):


dynamic c = MyClass();
c.Foo();

specificando la keyword dynamic indichiamo al complilatore che il riferimento c punta ad un oggetto “dinamico” nel senso che al momento della compilazione non viene controllato se Foo() esiste, ma a “runtime” l’infrastruttura DLR(Dynamic Language Runtime) cerca il membro Foo() e lo esegue, sollevando un’eccezione se il membro non viene trovato. Questo significa che quando dichiariamo un tipo dynamic il compilatore attraverso il nuovo insieme di classi(System.Dynamic namespace) crea i “metadati” che serviranno a runtime per “risolvere” i membri. Diciamo che è come avere tutti membri di una classe virtuali, ma la risoluzione viene fatta a runtime da una “logica” custom(questa è una mia libera interpretazione).

Chiaramente possiamo noi stessi creare dei tipi dinamici, ereditando da una classe System.Dynamic.DynamicObject e facendo l’override di alcuni metodi.

Vediamo un esempio reale. Mi capita spesso di dover lavorare con file Xml attraverso la classe XElement. Dato il seguente file Xml:

<?xml version="1.0" encoding="utf-8" ?>
<Anagrafiche>
  <Anagrafica id="1">
    <Nome>Marco</Nome>
    <Cognome>Rossignoli</Cognome>     
    <Contatti>
      <Cells>
        <Cell tipo="vodafone">+1234567890</Cell>
        <Cell tipo="wind">+0987654321</Cell>       
      </Cells>
      <Emails>
        <Email>nospam@nospam.no</Email>
        <Email>nospam2@nospam.no</Email>
        <Email>nospam3@nospam.no</Email>
      </Emails>
    </Contatti>
  </Anagrafica>
  <Anagrafica id="2">
    <Nome>Mario</Nome>
    <Cognome>Rossi</Cognome>
    <Contatti>
      <Cells>
        <Cell tipo="vodafone">+6789012345</Cell>
        <Cell tipo="3">+6543217890</Cell>
      </Cells>
      <Emails>
        <Email>nospam4@nospam.no</Email>
        <Email>nospam5@nospam.no</Email>
        <Email>nospam6@nospam.no</Email>
      </Emails>
    </Contatti>
  </Anagrafica>
</Anagrafiche>

devo leggere i vari elementi e attributi e stamparli in console. Posso utilizzare le classiche API della classe XElement in questo modo:

XElement el = XElement.Parse(File.ReadAllText("Anagrafica.xml"));

foreach (var anagraficaElement in el.Descendants("Anagrafica"))
{
    Console.WriteLine("id:{0}", anagraficaElement.Attribute("id").Value);
    Console.WriteLine("Nome:{0}", anagraficaElement.Element("Nome").Value);
    Console.WriteLine("Cognome:{0}", anagraficaElement.Element("Cognome").Value);
    Console.WriteLine("Contatti");

    foreach (var cell in anagraficaElement.Element("Contatti").Descendants("Cell"))
    {
        Console.WriteLine("Cellulare:{0} tipo:{1}", cell.Value, cell.Attribute("tipo").Value);
    }

   foreach (var email in anagraficaElement.Element("Contatti").Descendants("Email"))
   {
         Console.WriteLine("Email:{0}", email.Value);
   }

     Console.WriteLine("-----");
}

come possiamo vedere dal codice, per poter leggere gli attributi e gli elementi devo conoscere il funzionamento dell’Xml e delle API di XElement. Non sarebbe più comodo se potessi scrivere lo stesso codice in questo modo?

foreach (var anagrafica in el.Anagrafiche)
{
     Console.WriteLine("id:{0}", anagrafica.id);
     Console.WriteLine("Nome:{0}", anagrafica.Nome);
     Console.WriteLine("Cognome:{0}", anagrafica.Cognome);
     Console.WriteLine("Contatti");

     foreach (var contatti in anagrafica.Contatti)
     {
          foreach (var cellulari in contatti.Cells)
          {
              Console.WriteLine("Cellulare:{0} tipo:{1}", cellulari.Cell, cellulari.tipo);
          }

          foreach (var email in contatti.Emails)
          {
              Console.WriteLine("Email:{0}", email.Email);
          }
      }

      Console.WriteLine("-----");

}

La “nuova” sintassi è chiaramente più chiara e molto più agnostica ai vari concetti dell’xml(elementi, attributi etc…) e di XElement, l’unica cosa che dobbiamo fare è “leggere” l’xml e richiedere l’elemento/attributo che ci interessa, qualcuno a runtime saprà come farlo.

Il DLR ci permette di realizzare questa “magia”, ovvero tutto quello che dobbiamo fare è rendere “dinamici” gli oggetti che devono “risolvere a runtime” i vari membri. Nel nostro esempio sono i riferimenti in grassetto. Cerco di spiegarmi meglio, l’idea è demandare ad un nostro pezzo di codice l’effettiva risoluzione delle varie proprietà richieste, come ad esempio l’id di anagrafica, il nome di anagrafica, il Cell di cellulari etc…il codice completo risulterà così:

XElement doc = XElement.Parse(File.ReadAllText("Anagrafica.xml"));

dynamic el = doc.AsDynamic();

foreach (var anagrafica in el.Anagrafiche)
{
    Console.WriteLine("id:{0}", anagrafica.id);
    Console.WriteLine("Nome:{0}", anagrafica.Nome);
    Console.WriteLine("Cognome:{0}", anagrafica.Cognome);
    Console.WriteLine("Contatti");

    foreach (var contatti in anagrafica.Contatti)
    {
        foreach (var cellulari in contatti.Cells)
        {
             Console.WriteLine("Cellulare:{0} tipo:{1}", cellulari.Cell, cellulari.tipo);
        }

        foreach (var email in contatti.Emails)
        {
              Console.WriteLine("Email:{0}", email.Email);
        }
    }

    Console.WriteLine("-----");

  }

semplicemente ci serve un modo per avere un “wrapper” dynamic sul nostro XElement, sarà la logica che mettiamo nel nostro DynamicObject a cercare attraverso le varie API XElement l’elemento/attributo richiesto. Nella MIA implementazione ho usato un’extension method su XElement per eleganza, ma non è obbligatorio in quanto come vedremo tra un secondo la definizione del nostro dynamic object è una normale classe che eredita da System.Dynamic.DynamicObject e ha un costruttore al quale possiamo passare l’istanza di XElement.

E ora vediamo la definizione della classe “magica”:

  public static class DynamicXmlExtension
  {
      public static dynamic AsDynamic(this XElement xml)
      {
          return new DynamicXml(xml);
      }

       public class DynamicXml : DynamicObject
      {
          public DynamicXml(XElement element)
          {
              _element = element;
          }

          private bool TryGetMemberLogic(GetMemberBinder binder, out object result)
          {
               ….logica interna di ricerca degli elementi/attributi che nascondo volontariamente
               in quanto incompleta, non testata e a scopo dimostrativo…alla fine non fa 
               altro che utilizzare binder.Name con le API XElement             
          }

          public override bool TryGetMember(GetMemberBinder binder, out object result)
          {
                return TryGetMemberLogic(binder, out result);
          }

          public override string ToString()
          {
              return _element.ToString();
          }

        }

  }


la classe contiene 2 cose fondamentali: la prima è l’extension method che ritorna l’oggetto di tipo dynamic e la seconda è l’implementazione del nostro tipo DynamicXml che eredita da System.Dinamic.DynamicObject. Il segreto per realizzare la “magia” sta nel ridefinire dei metodi della classe base DynamicObject. Abbiamo un bel pò di metodi che ci permettono di gestire la risoluzione di praticamente qualsiasi membo di una classe(ma non solo). Nel nostro esempio quello che ho dovuto ridefinire è il Get di un membro(ricodate anagrafica.Nome), quindi ho fatto l’override di TryGetMember(come possiamo notare tutti i metodi cominciano con TryXXX). TryGetMember mi fornisce 2 parametri, il primo GetMemberBinder attraverso la proprietà Name mi comunica il nome del membro richiesto(ad esempio in caso di anagrafica.Nome binder.Name sarà Nome, GetMemeberBinder contiene altre interessanti proprietà che non tratterò per semplicità) il secondo è una variabile di out che la mia logica di ricerca deve assegnare. Insomma in soldoni cerco il binder.Name nel mio xml attraverso le API XElement e quando trovo l’elemento lo assegno a result. I parametri forniti da questi metodi variano a seconda della caratteristica che stiamo cercando di risolvere in modo “dinamico” a runtime(ogni TryXXX ha i suoi parametri tipizzati).

Carino o no?

Il DLR è un framework molto potente ed interessante, oltre a fare queste “magie” viene impiegato per risolvere tanti altri problemi, per una trattazione approfondita potete partire da qua Dynamic Language Runtime Overview.

Per scaricare una demo funzionante clicca qua

Attenzione non utilizzate il codice in produzione, non è completo non è testato ed è a scopo dimostrativo; inoltre mi sono inventato una mia logica di ricerca che può non piacere o risultare scomoda…ereditate e implementate la vostra ;-)

Correntemente valutato 5.0 da 2 utenti

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

.Net

System.Threading.Tasks.Task implementa IAsyncResult(.NET 4.0 Beta 2)

by Marco 13. gennaio 2010 14.18

L’ IAsyncResult design pattern è un pattern per l’esecuzione asincrona di operazioni che viene largamente usato all’interno del framework in ogni sua parte; consiste nella scrittura di due metodi che permettono di iniziare un’operazione in modo asincrono e di un metodo che la completa, un esempio di una classe che implementa questo pattern potrebbe essere:

    public class AsyncLib
   {
       public int Foo(int parameter)
       {
           ...operazione
       }

       public IAsyncResult BeginFoo(int parameter, AsyncCallback callback, object state)
       {
          ...chiamata a Foo(int parameter) in thread separato e ritorno di un oggeto
          che implementa IAsyncResult
       }

       public int EndFoo(IAsyncResult asyncResult)
       {
           …se l’operazione è finita torno il risultato altrimenti blocco il thread che ha chiamato
       }
   }

il funzionamento è abbastanza semplice: chiamo BeginOperazione che ritorna immediatamente un’istanza di una classe che implementa l’interfaccia IAsyncResult che possiamo interrogare per sapere a che punto è la nostra operazione, o possiamo passare un delegate di tipo AsyncCallBack al metodo stesso per farci chiamare una volta che l’operazione è finita. Quando l’operazione asincrona è terminata(lo sappiamo grazie all’oggetto IAsyncResult o perchè ci viene chiamata la callBack) dobbiamo chiamare il metodo EndOperazione e passare l’istanza ritornata dal metodo BeginOperazione, a quel punto abbiamo in mano il risultato e possiamo farci quello che vogliamo. Questa spiegazione non è completa, ma non è lo scopo del post vi lascio il link alla documentazione ufficiale Asynchronous Programming Design Patterns. Lo stesso pattern viene implementato automaticamente se utilizziamo un delegate, ovvero viene compilata per noi una classe con i metodi Begin/End.

Se dobbiamo far implementare questo pattern alle nostre librerie la cosa più complessa da fare è quella di creare una classe che implementi IAsyncResult nel modo corretto e sincronizzare il tutto con il lavoro asincrono. Le cose da prendere in esame non sono poi così banali, dobbiamo accodare il lavoro da “qualche parte”(dipende da quale tipo di thread vogliamo utilizzare, thread pool, un nostro thread etc…),implementare ciò che l’interfaccia ci richiede(le cui cose più complesse sono come gestire l’oggetto di sincronizzazione e alcuni stati richiesti dall’oggetto in modo perfomante e corretto) e chiamare la callback in caso venga fornita alla fine dell’operazione asincrona. Problema ancora più subdolo è il fatto che la nostra libreria potrebbe essere chiamata in contesti di threading diversi, quindi in caso di callback dobbiamo assicurarci che tutto rispetti le regole di questo contesto. L’implementazione costa un pò di righe di codice che non sono così banali a chiunque.

Il team delle Task Parallel Library ha fortunatamente pensato anche a questo e ha gentilmente fatto implementare alla classe Task l’interfaccia IAsyncResult. Questo fa si che scrivere con .NET 4.0 un custom IAsyncResult diventi un gioco da ragazzi, di seguito un esempio:

  public class AsyncLib
   {
       public int Foo(int millisecond)
       {
           //simulo un carico di lavoro
           Thread.Sleep(millisecond);
           //simulo un risultato
           return new Random().Next(int.MaxValue);
       }

       public IAsyncResult BeginFoo(int i, AsyncCallback callback,
           object state)
       {
          

          Task<int> task = new Task<int>(o => Foo(i), state);

           task.ContinueWith(t =>
           {
               if (callback != null)
                   callback(t);
           },
           SynchronizationContext.Current == null ?
           TaskScheduler.Default :
           TaskScheduler.FromCurrentSynchronizationContext()
);

           task.Start();

           return task;

         }

       public int EndFoo(IAsyncResult asyncResult)
       {
           Task<int> result = asyncResult as Task<int>;

           if (result == null)
               throw new ArgumentException("Bad async result.");

           return result.Result;
       }
   }

cosa ne dite?Semplicemente la nostra Begin ritorna un task che esegue prima la chiamata a Foo in modo asincrono e poi attraverso ContinueWith esegue la callback(in caso venga passata) nel constesto di threading adeguato
(TaskScheduler.FromCurrentSynchronizationContext() o TaskScheduler.Default). Se contiamo le righe di codice sono 4 per la Begin(sono dovuto andare a capo per farci stare tutto)e 3/4 per la End. Con così poco semplice codice utilizzare questo pattern sarà alla portata di tutti, in quanto l’unica cosa non chiarissima è forse il check del contesto per scegliere il TaskScheduler adeguato, ma siamo in Beta 2 magari qualcosa di meglio lo pensano, per il resto non si vede l’ombra di XXXResetEvent, lock, volatile, ThreadPool, Thread,WaitXXX etc….sono solo 2 Task uno “attaccato” alla fine dell’altro…semplice no?

…ah dimenticavo, chiaramente funziona ovunque, Console app, Windows Form app, WPF app etc…

Se volete una demo contattatemi

Vota questo post per primo

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

.Net | Concurrent Programming | Multithreading

TaskScheduler.FromCurrentSynchronizationContext() (.NET 4.0 Beta 2)

by Marco 7. gennaio 2010 20.39

Tutti coloro che hanno sviluppato interfaccie che gestiscono una grande quantità di dati o che eseguono lunghe operazioni, si sono dovuti scontrare prima o poi con il problema del “blocco” dell’interfaccia dovuto al fatto che la “pesantezza” dell’operazione veniva eseguita nel famoso “thread di UI” cioè quel thread che ha il compito di gestire la coda dei messaggi associata ai controlli che lui stesso ha creato. L’indisponibilità di questo thread(speso a fare operazioni “lunghe”) porta l’interfaccia a bloccarsi in quanto i messaggi nella coda non vengono gestiti e quindi la nostra interfaccia non si può ridisegnare correttamente o reagire all’attività dei nostri utenti.

Per ovviare a questo problema l’unica soluzione è quella di effettuare l’operazione “lunga” in un thread separato, così da liberare il “thread di UI” che può senza problemi gestire la sua bella coda di messaggi. L’unico problema di questo approccio è il fatto che nel momento che dobbiamo riflettere il risultato dell’ operazione “lunga” sull’interfaccia non lo possiamo fare da un thread che non sia quello di UI. L’unico modo di risolvere questo problema è quello di fare il “marshal” sul “thread di UI” ovvero ci serve un meccanismo per passare i dati al thread di UI e far fare a lui la modifica dei nostri controlli. I 2 principali framework grafici che “soffrono” di questo problema sono chiaramente Windows Form e WPF. Su internet si trovano tonnellate di articoli che spiegano come fare il “marshal” nelle varie piattaforme, l’operazione è abbastanza semplice, l’unico difetto è che purtroppo le modalità sono differenti da un framework ad un’altro(esempio l’interfaccia ISyncronizeInvoke per Windows Form e la classe Dispatcher per WPF) e questo è un bel problema per chi deve ad esempio scrivere una libreria che deve essere asincrona e utilizzabile ALLO STESSO MODO su qualsiasi piattaforma grafica venga usata(diciamo che più che di piattaforma grafica possiamo parlare di contesto di esecuzione).

Una delle possibilità che abbiamo per generalizzare la possibilità di gestire il marshal è quella di utilizzare la classe SyncronizationContext che attraverso la proprietà statica Current ci mette a disposizione un paio di metodi(Post se vogliamo un’esecuzione asincrona o Send la vogliamo sincrona) per eseguire un delegate nel giusto Context(diciamo il thread di UI se stiamo usando WPF o WindowsForm, ma context è un concetto generico).

Ad esempio se vogliamo modificare il content di un bottone in WPF un’ipotetico handler dell’evento click potrebbe essere:

private void button1_Click(object sender, RoutedEventArgs e)
{          
  SynchronizationContext context = SynchronizationContext.Current;
   ThreadPool.QueueUserWorkItem(a =>
           {
              System.Threading.Thread.Sleep(5000);//Simulo il carico di lavoro
             context.Post(o=>this.button1.Content=o,"Nuova Content del bottone"); //modifico una proprietà di interfaccia
           });
  }

in questo esempio prima salvo il Current context attraverso la proprietà SyncronizationContext.Current e poi in un thread del thread pool di .NET(quindi non un thread di UI) faccio il “marshal” asincrono usando il metodo Post sul context salvato(il context nel thread di thread pool non è valido). Il fatto che sto utilizzando WPF significa che qualcuno(il runtime di WPF) ha “attaccato” come Current context una implementazione personalizzata(la classe è la DispatcherSynchronizationContext nel namespace System.Windows.Threading) della classe SynchronizationContext che al suo interno usa la classe Dispatcher per fare il marshal in modo corretto.

Questo significa che se devo eseguire operazioni asincrone, ma non voglio legarmi a nessuna piattaforma(non solo UI) applicativa utilizzando questa classe(sperando che qualcuno abbia correttamente implementato una versione della classe SyncronizationContext) e non voglio avere problemi nel momento in cui dovrò eseguire la “callback” di finalizzazione dell’operazione, utilizzare l’astrazione attraverso SyncronizationContext mi risolve il mio problema di “generalizzazione”.

Se volete scrivere ancora meno codice e restare ad un livello ancora più alto sotto il namespace System.ComponentModel troviamo la classe AsyncOperationManager che fa un pò di lavoro per noi(come ad esempio salvarsi il context o inizializzare un context di default se non è presente, come ad esempio in una console application, il default context utilizza il thread pool nel Send/Post)attraverso un metodo “factory” di operazioni asincrone, permettendoci di focalizzarci di più sul problema di “business” e meno su quello “tecnico”, il System.ComponentModel.BackgroundWorker si basa su questa classe.

Esempio:

private void button1_Click(object sender, RoutedEventArgs e)

//creo il wrapper per l’operazione asyncrona, controlla se il context esiste o ne
//imposta uno di default che usa il ThreadPool .NET
AsyncOperation operation = AsyncOperationManager.CreateOperation(null);                   

System.Threading.ThreadPool.QueueUserWorkItem(a =>
               {
                   System.Threading.Thread.Sleep(5000);//simulo il carico di lavoro
                  

                   //Faccio il post dell’operazione sul contesto giusto e notifico il
                   //context sottostante
                   operation.PostOperationCompleted(o =>
                   {
                       this.button1.Content = o;
                   }, "Nuova Content del bottone");                                      
               });
}

Il metodo PostOperationComplete notifica in modo automatico il Context sottostante che l’operazione è terminata, in caso il context in questione avesse bisogno di saperlo per motivi architetturali(altrimenti avremmo dovuto chiamare prima il metodo Post() e poi il metodo OperationCompleted()). L’esempio non è esaustivo, ma da l’idea del senso per cui è stato creato per approfondimenti cercate nella guida o sul web, lo scopo di questo blog non è l’AsyncOperationManager.

Fortunatamente anche con le Task Parallel Library abbiamo la possibilità di sfruttare questo meccanismo in modo veramente semplice…il codice è più chiaro della spiegazione:

private void button1_Click(object sender, RoutedEventArgs e)
       {
              Task.Factory.StartNew(() =>
               {
                   Thread.Sleep(5000);//Simulo il carico
                   return "Nuova Content del bottone";
               })
               .ContinueWith(taskPrecedente =>
                   {
                       this.button1.Content = taskPrecedente.Result;
                   }, TaskScheduler.FromCurrentSynchronizationContext()
                   );

       }

Il metodo ContinueWith accetta come parametro tra i suoi overload un’oggetto di tipo TaskScheduler il quale ha un metodo statico FromCurrentSynchronizationContext che si occupa di creare un TaskScheduler del giusto tipo per il contesto in cui siamo.
Questo significa che l’operazione pesante(StartNew()) viene fatta in un thread separato e l’assegnazione del risultato(ContinueWith()) al nostro controllo viene “postato” sul thread di UI, grazie al fatto che abbiamo indicato uno scheduler conscio del fatto che siamo in un contesto di funzionamento per quanto riguarda il threading “particolare”(sotto le coperte utilizza il SyncronizationContext).

Non so cosa ne pensate, ma la sintassi per scrivere codice asincrono lato client con le TPL(task parallel library) è un bel passo avanti e alla portata di tutti…buon divertimento.

Vota questo post per primo

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

Multithreading | .Net

Axum al PDC

by Marco 5. gennaio 2010 12.26

Ho già parlato in passato di questo “incubation project” e vi consiglio di guardare questa sessione di Niklas Gustafsson che illustra in modo molto chiaro il motivo per cui è necessario avere un linguaggio “ad hoc” per poter sviluppare in modo corretto/produttivo applicazioni parallele altamente scalabili sulle piattaforme multicore di oggi e domani.

Certamente non tutto il codice che scriviamo deve per forza essere parallelo, una GUI, una logica di business, il codice di accesso ai dati, non hanno sempre questi requisiti, ma vi sono alcune parti di un programma in cui questa possibilità può rendere l’applicazione molto più soddisfaciente.

Axum è un linguaggio che implementa il parallelismo attraverso il paradigma di comunicazione denominato “Message-Passing” dove l’idea principale è quella di avere degli agenti(concettualmente delle classi che fanno qualcosa) che operano su dei dati che definiscono il dominio(ad esempio le classi che contengono i dati su cui fare qualcosa). La chiave di tutto è il fatto che gli agenti possono scambiare tra loro dati solo attraverso messaggi che trasportano dati che possono essere usati in un dominio. Questa constraint da la possibilità di specificare che un agente ha la possibilità di modificare i dati di un dominio, operazione preclusa agli altri agenti che scambiano dati attraverso “copie” e non attraverso riferimenti ai dati stessi.

Gli elementi principali di Axum sono:

-Agenti: gli utilizzatori dei dati del dominio(possono stare in-process o out-of-process, permettendo così di avere un "distributed programming model").

-Dominio: i dati che vengono usati dagli agenti(in modo esclusivo ad esempio)

-Channel: l’interfaccia di comunicazione tra un agente e gli altri agenti

-Schema: definiscono le constraints sui channels e sui messaggi che vengono scambiati dagli agenti

Questo stile di programmazione permette di superare un bel po' di problemi a cui dobbiamo far fronte quando scriviamo un’applicazione che deve “andare in parallelo” ed essere diciamo “asincrona” e “scalabile”. I problemi fondamentali sono quelli dell’isolamento degli stati(evitare lo sharing di parti di memoria attraverso copie e non riferimenti diretti a questa), la sincronizzazione e locking(è un task complesso e pieno di insidie lasciamolo fare ad un runtime) , consumo di risorse(ogni thread in .NET consuma 1MB minimo), scalabilità(sfruttamento di multicore, minimizzare il context switch tra i thread etc…), ma ce ne sono anche altri meno macroscopici.

Il progetto è ancora nei Labs di Microsoft…speriamo non uccidano il bambino nella culla.

Buona visione http://microsoftpdc.com/Sessions/VTL02

P.S.: buon 2010 a tutti.

Correntemente valutato 5.0 da 1 utenti

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

.Net | Concurrent Programming | Parallel Programming

Disclaimer
Le opinioni espresse in questo blog sono mie opinioni personali.

© Copyright 2012 Knowledge.CreateAsync()