Month: September 2011

Perchè Windows Embedded Compact è qui per restare

E’ dall’evento Build in cui è stato presentato Windows 8 che mi faccio continuamente la stessa domanda : “Se Windows 8 sarà possibile eseguirlo anche su macchine con processori ARM, vedi tablet, quali sono le intenzioni di Microsoft riguardo Windows Embedded Compact”.

Ho postato il mio dubbio anche sul forum ufficiale della Microsoft ma nessuno ha saputo darmi una risposta valida, poichè nessuno può prevedere le intenzioni della Microsoft stessa.

Oggi ho trovato un articolo interessante sul sito WindowsForDevice e scritto da Maharajan Veerabahu, che finalmente ha saputo dare delle motivazione per le quali “Windows Embedded Compact è qui per restare”.

Scelta dell’hardware

Windows 8 è comunque orientato ai processori ARM di fascia alta per il mercato consumer (tablet) mentre con Windows CE si può mirare anche alla realizzazione di sistemi embedded il cui processore ARM è di fascia medio/bassa e quindi a costi inferiori.

Per quanto sia stato sicuramente migliorato rispetto a Windows 7, Windows 8 ha molta più “fame” di memoria RAM rispetto a Windows CE per il quale talvolta bastano anche soli 16 MB di RAM per un sistema perfettamente funzionante.

Sviluppo dei driver e shared source code

Con Windows CE si possono sviluppare drivers di tutti i tipi per device di qualsiasi categoria che possono tranquillamente interfacciarsi al sistema operativo. Con Windows 8 bisognerà vedere cosa sarà messo a disposizione nel DDK (Driver Development Kit).

Inoltre, Microsoft fornisce la maggior parte dei sorgenti di Windows CE sui quali si ha anche la possibilità di intervenire in casi estremi. Non è pensabile una soluzione del genere per Windows 8.

Performance

Sicuramente Windows CE fornisce un boot-time inferiore rispetto a Windows 8 (nonostante i notevoli passi avanti). C’è una gestione più mirata del power-management e soprattutto è da considerarsi a tutti gli effetti un sistema hard-real time, caratteristica che non interessa assolutamente al mercato consumer per Windows 8.

Per quanto riguarda la sicurezza, essendo Windows CE modulare, lo sviluppatore ha anche la facoltà di rimuovere quei componenti che sono facilmente attaccabili e non necessari.

Conclusioni

Sono assolutamente d’accordo con quanto scritto da Maharajan Veerabahu e spero che la Microsoft tenga conto di tutte queste considerazioni, in quanto non esiste solo il mercato consumer che fa uso dei processori ARM ma un mercato parallelo di sistemi embedded che oramai troviamo in un qualsiasi oggetto.

Vi rilascio all’articolo originale per approfondire questo tema interressante.

Extension Methods non supportati nel .Net Micro Framework ? Ecco la soluzione !

Purtroppo, il .Net Micro Framework non mette a disposizione nativamente gli Extension Methods. Infatti, se proviamo a compilare il seguente frammento di codice, che aggiunge un generico metodo alla classe String …

public static class StringExtension
{
    public static void Method(this String s)
    {
        // eblaborazione
    }
}

… otterremo il seguente errore di compilazione :

Cannot define a new extension method because the compiler required type ‘System.Runtime.CompilerServices.ExtensionAttribute’ cannot be found. Are you missing a reference to System.Core.dll?

Ciò è dovuto all’assenza dell’ExtensionAttribute che permette appunto di implementare gli extension methods.

Per risolvere questo problema, basta definire la seguente classe all’interno del nostro progetto :

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Assembly |
                    AttributeTargets.Class |
                    AttributeTargets.Method)]
    public sealed class ExtensionAttribute : Attribute
    {
    }
}

Chissà se la versione 4.2, in procinto di uscire, chiuderà questa enorme quanto banalissima falla.

Elaborazioni con timeout … gli Execution Constraints

In molti casi, si rende necessario eseguire un’elaborazione entro un certo intervallo di tempo, definendo un timeout di fine esecuzione; se l’elaborazione non viene conclusa entro il timeout prefissato, viene gestita la corrispondente condizione di errore.

Il .Net Framework, per numerose classi, mette a disposizione dei metodi che eseguono determinate elaborazioni per le quali è possibile impostare un timeout. Purtroppo, nel .Net Micro Framework, non esiste il medesimo supporto nella maggior parte delle situazioni.

Per questo motivo, è stato introdotto il concetto degli Execution Constraints, attraverso i quali è possibile monitorare se una certa elaborazione sia completata o meno in un determinato intervallo di tempo. Il tempo di esecuzione è monitorato da un background thread. Al completamento dell’elaborazione, il monitoring viene arrestato ed il constraint viene “disinstallato”.

La classe utilizzata è la ExecutionConstraint che mette a disposizione l’unico metodo statico Install() che prevede I seguenti parametri :

  • timeout : timeout dell’operazione in millisecondi;
  • priority : la priorità del thread di monitoring (attualmente sembra che il micro framework non tenga conto di questo parametro);

Di seguito è illustrato un esempio di applicazione :

ExecutionConstraint.Install(1000, 0);
// elaborazione
ExecutionConstraint.Install(-1, 0);

Attraverso la prima chiamata ad Install(), definiamo un timeout massimo di 1000 ms (1 sec) per tutto il codice che verrà eseguito sino alla successiva chiamata dello stesso metodoInstall(), per il quale il parametro di timeout impostato a –1 ha il significato di “disinstallare” il monitoring.

Nel caso in cui, l’elaborazione non viene completata entro il timeout prefissato, viene sollevata una ConstraintException.
In base a quanto detto, un buon pattern di utilizzo sarà il seguente :
try
{
    ExecutionConstraint.Install(1000, 0);
    // elaborazione
}
catch (ConstraintException cEx)
{
    // elaborazione non terminata entro timeout
}
finally
{
    ExecutionConstraint.Install(-1, 0);
}

Nullable.Equals(object) … comportamento “strano” che ha una spiegazione !

Ieri, in ufficio con alcuni miei colleghi, mi sono imbattuto in un comportamento alquanto strano del metodo Equals(object) della struct Nullable<T>.

Consideriamo il seguente frammento di codice :

short? x = 1;
bool b = x.Equals(1);

Secondo voi….quanto vale la variabile b ? Ebbene….magicamente false !

A questo punto consideriamo il seguente frammento di codice :

short? x = 1;
// caso 1
bool b = x.Equals(1);
// caso 2
b = x.Equals((short)1);
// caso 3
short y = 1;
b = x.Equals(y);

Il “caso 1” è ovviamente quello appena visto e ritorna “stranamente” b uguale a false. Il “caso 2” e “caso 3” si comportano correttamente fornendo un valore true.

Cambiamo il “caso 1” nel modo seguente :

int? x = 1;
bool b = x.Equals(1);

In questo caso, abbiamo semplicemente modificato la dichiarazione del nullable type dashort? a int? ed il valore di b diventa “magicamente” true !

Ecco che a questo punto, dotandomi di Reflector ho cominciato ad indagare sull’implementazione del metodo Equals(object) della struct Nullable<T> che riporto di seguito.

public override bool Equals(object other)
{
    if (!this.HasValue)
    {
        return (other == null);
    }
    if (other == null)
    {
        return false;
    }
    return this.value.Equals(other);
}

Dopo aver eseguito un paio di controlli preliminari sul fatto che la struct abbia un valore e che l’oggetto passato per il confronto non sia null, viene invocato il metodo Equals(object) del tipo T del campo value (interno alla struct Nullable<T>).

Considerando il caso in cui avevamo la dichiarazione short?, ossia Nullable<short>, il metodo che viene invocato sarà ovviamente Int16.Equals(object) la cui implementazione è la seguente :

public override bool Equals(object obj)
{
    return ((obj is short) && (this == ((short) obj)));
}

L’utilizzo dell’operatore is, per la verifica del tipo del parametro, svela l’arcano !

Come sappiamo, tutti i numeric literals (il numero “1” nel nostro caso) sono trattati implicitamente come Int32, per cui la chiamata x.Equals(1) (dove x è di tipo short?) restituisce “correttamente” false, in quanto obj non sarà short ma int !

In tutti gli altri casi, dichiarando esplicitamente una variabile di tipo short (si veda short y = 1) oppure eseguendo il cast esplicito a short del numeric literal (si veda x.Equals((short)1)), forziamo il tipo (coincidente con short? x) ed il confronto ritorna un valore corretto.

Questo spiega anche il perchè del fatto che modificando la dichiarazione da short? x a int? x, otteniamo un valore corretto per x.Equals(1)….in quanto il numeri literal “1” come già detto è implicitamente un Int32 !

In conclusione…..attenzione all’uso del metodo Equals(object) e dei numeric literals nei confronti !!

Rilasciata la RC2 del .Net Micro Framework 4.2

E’ stata rilasciata la RC2 del .Net Micro Framework 4.2, il cui rilascio definitivo era pianificato per la seconda metà del 2011. A quanto pare con i tempi ci siamo, considerando che questa release candidate dovrebbe essere praticamente uguale alla versione definitiva.

Di seguito un link sul blog di Colin Miller che segue da vicino l’evoluzione open source di questa piattaforma ed il link per il download.

Da byte[] a String con il .Net Micro Framework

Spesso, dato un array di byte con codifica UTF8, si rende necessaria la relativa conversione in una stringa. Purtroppo, il .Net Micro Framework non mette a disposizione il metodoEncoding.UTF8.GetString(byte[] bytes) utile per questo scopo.

Il metodo più veloce per ottenere il medesimo risultato è il seguente :

byte[] bytes;
...
...
string s = new String(Encoding.UTF8.GetChars(bytes));

E’, in pratica, necessario ricavere prima l’array di char corrispondenti e poi instanziare un oggetto String inizializzandolo con tale array.