Posts
255
Comments
330
Trackbacks
7
gennaio 2009 Entries
Google ha qualche problema…

Negli ultimi 10 minuti, qualsiasi cosa cerco con Google, sotto ogni voce trovata, viene visualizzata la voce: “Questo sito potrebbe arrecare danni al tuo computer”

image

Ovviamente con altri motori di ricerca non ho nessun problema . Qualcuno visualizza gli stessi risultati?

posted @ sabato 31 gennaio 2009 15.52 | Feedback (11)
Precauzioni…

Leggevo questo articolo a riguardo di una nuova minaccia informatica, probabilmente  molti di voi ne sono già a conoscenza…

posted @ sabato 24 gennaio 2009 12.19 | Feedback (4)
A volte ritornano…

Ricordate la vecchia Polaroid? Adesso è in formato digitale: Punta, Clicca e Stampa :-)

posted @ mercoledì 14 gennaio 2009 12.09 | Feedback (0)
PLINQ: Task e Future<T>

La  classe System.Threading.Task.Task è una classe che rappresenta un'operazione asincrona, o meglio, un wrapper di un delegate contenente tutte le informazioni necessarie per conoscere lo stato di avanzamento di un’operazione, ad esempio se è terminata perchè completata o interrotta dall’utente, mediante le proprietà IsCompleted e IsCanceled o per interrompere l'esecuzione dell'operazione, chiamando l’apposito metodo Cancel. Essendo la classe Task priva di costruttori pubblici, per crearne un'istanza è necessario utilizzare uno degli overload del metodo statico Create. Per attendere il termine di un'operazione asincrona, un'istanza della classe Task mette a disposizione il metodo Wait (o meglio tre overload): Wait() senza parametri che attende la conclusione delle operazioni, Wait (TimeSpan span) che accetta un oggetto TimeSpan per indicare il tempo di attesa in millisecondi per il completamento delle operazioni ed infine Wait (int milliseonds) che accetta il numero di millisecondi per cui si vuole attendere la conclusione delle operazioni. Possiamo vedere immediatamente la classe Task in azione con un piccolo esempio. Supponiamo di avere la seguente funzione il cui scopo è creare un file di testo contenente un certo numero di righe, secondo il valore degli argomenti passati:

1 private static void WriteFile(IsolatedStorageFile storage, int start, int count) 2 { 3 string fileName = string.Format("start_{0}.txt", start); 4 5 lock (storage) 6 { 7 using (IsolatedStorageFileStream sw = new IsolatedStorageFileStream(fileName, System.IO.FileMode.OpenOrCreate, storage)) 8 { 9 using (System.IO.StreamWriter swriter = new System.IO.StreamWriter(sw)) 10 { 11 for (int i = start; i < start + count; i++) 12 swriter.WriteLine("Item#{0}", i); 13 } 14 } 15 } 16 }

Supponiamo di voler scrivere 5 file ed attendere per il completamento delle operazioni, possiamo scrivere qualcosa del tipo: 
 

1 Task tFile1 = Task.Create(delegate { WriteFile(storage, 1, 10); }); 2 Task tFile2 = Task.Create(delegate { WriteFile(storage, 11, 10); }); 3 Task tFile3 = Task.Create(delegate { WriteFile(storage, 21, 10); }); 4 Task tFile4 = Task.Create(delegate { WriteFile(storage, 31, 10); }); 5 Task tFile5 = Task.Create(delegate { WriteFile(storage, 41, 10); }); 6 Console.WriteLine("Writing..."); 7 //Attende il completamento di tutti i task, 8 Task.WaitAll(new Task[] { tFile1, tFile2, tFile3, tFile4, tFile5 });


Invece di richiamare il metodo Wait (o uno dei suoi overload per ogni istanza di Task, possiamo richiamare il metodo statico WaitAll (anch'esso definito con tre  overload) che accetta come primo parametro un vettore di oggetti  Task (o da essi derivati), per i quali attendere il completamento delle operazioni. Fin qui tutto bene, ma il metodo WriteFile, esegue l'operazione senza ritornare nessun valore. Supponiamo allora di voler eseguire la scansione "parallela" di un certo numero di directory su disco per ottenere il numero di file di testo (*.txt) contenuti nelle directory. Una funzione molto semplice potrebbe essere di questo tipo:

1 public static int ScanDirectory( string path, string searchPattern) 2 { 3 return System.IO.Directory.GetFiles(path, searchPattern).Count(); 4 }

In questo caso, a meno di creare una classe personalizzata che derivi da Task, possiamo utilizzare la classe Future<T>, che deriva da Task, e che permette il recupero di un valore di ritorno da un'operazione asincrona. Semplicemente possiamo scrivere:

1 Future<int> tSearch1 = Future.Create(() => ScanDirectory(@"C:\", "*.txt")); 2 Future<int> tSearch2 = Future.Create(() => ScanDirectory(@"C:\DIR1", "*.txt")); 3 Future<int> tSearch3 = Future.Create(() => ScanDirectory(@"C:\DIR2", "*.txt")); 4 Task.WaitAll(new Future<int>[] { tSearch1, tSearch2, tSearch3 });

Per quanto detto precedentemente, anche in questo caso è possibile utilizzare il metodo statico WaitAll per attendere il completamento delle operazioni. Per recuperare il numero di file di testo trovati nelle directory, accediamo alla proprietà Value di ogni istanza di Future<int>:

1 int filesCount = tSearch1.Value + tSearch2.Value + tSearch3.Value; 2 Console.WriteLine("Files Count:" + filesCount);

Ci sono delle piccole osservazioni da fare. Supponiamo di modificare la funzione ScanDirectory in questo modo:  

1 public static int ScanDirectory( string path, string searchPattern) 2 { 3 System.Threading.Thread.Sleep(3000); 4 return System.IO.Directory.GetFiles(path, searchPattern).Count(); 5 }

e di eseguire il codice seguente:

1 Future<int> tSearch1 = Future.Create(() => ScanDirectory(@"C:\Lavoro", "*.txt")); 2 tSearch1.Wait(1000); 3 int filesCount = 0; 4 filesCount = tSearch1.Value; 5 Console.WriteLine("Files Count:" + filesCount);

Supponendo che la directory “C:\Lavoro” contenga 4 file di testo, ci si potrebbe aspettare che il valore visualizzato sulla console sia zero (dato che Wait attende per solo un secondo), invece, verrà visualizzato il valore corretto, dato che l’accesso alla proprietà Value  sì comporta come Wait senza parametri. Si potrebbe allora pensare di utilizzare  il metodo Cancel(), subito dopo il Wait, ma verrebbe sollevata un'eccezione  quando si tenta di recuperare  il valore da Value

1 tSearch1.Wait(1000); 2 tSearch1.Cancel();

Una possibile soluzione è quella di sfruttare le proprietà IsCanceled (o in casi diversi IsCompleted), in questo modo:  

1 if(!tSearch1.IsCanceled ) filesCount = tSearch1.Value;

La semplificazione introdotta da queste classi per la gestione delle operazioni asincrone è veramente impressionante.

posted @ lunedì 12 gennaio 2009 18.29 | Feedback (2)
The setup failed to read IIsMimeMap table…

Finalmente sono riuscito a ritagliare del tempo per formattare e ripristinare il mio portatile, prima che arrivi il mio periodo “caldo” (causa lavoro e Università). In questi giorni, mi è capitato di dover rimuovere da un PC, SQL Server 2005, nel caso in cui durante il processo di disinstallazione si presenti il messaggio : Il programma di installazione non riesce a leggere tabella IIsMimeMap. Il codice di errore è-2147024893 (o The setup failed to read IIsMimeMap table. The error code is –2147024893 )

image

la soluzione è in questo articolo, in pratica si tratta di disabilitare in sequenza i servizi Servizio  di Amministrazione di IIS e Servizio Pubblicazione sul Web prima di procedere con la disinstallazione

posted @ domenica 11 gennaio 2009 20.34 | Feedback (0)
Windows 7 e Paint…

Ho appena terminato di installare la beta di Windows 7 su macchina virtuale (velocemente e senza nessun problema), e “girovagando” ho dato uno sguardo anche a Paint, sono rimasto (positivamente) sorpreso:

Windows 7

image 

Windows Vista

image

Le immagini si commentano da sole :-)

Trovo molto comode le utility Sticky Notes ( per aggiungere sul desktop delle note tipo post-it) e Snipping Tool, per catturare e modificare delle aree dello schermo. La calcolatrice oltre ad aver subito un piccolo "restyling" ha delle nuove funzionalità, come la possibilità di eseguire operazioni (addizioni e sottrazioni) su date e la conversione tra unità di misura. C'è anche  l'opzione Templates che stuzzica la fantasia... Certo non sono queste le funzionalità che rendono un sistema operativo un Buon sistema operativo, ma se il buongiorno si vede dal mattino...


posted @ domenica 11 gennaio 2009 20.32 | Feedback (4)
OrderBy (e OrderByDescending) e comparatori personalizzati

Supponiamo di lavorare con due classi del tipo seguente:

image

e di voler utilizzare Linq To Objects per eseguire delle operazioni sul nostro insieme di dati, composto da un array di oggetti Documento:

1 Documento[] documenti = new Documento[]{ 2 new Documento ("10",new Cliente {Nome="Pietro",Cognome ="Libro",CodiceFiscale="ABA"}), 3 new Documento ("2",new Cliente {Nome="Pietro",Cognome ="Bianchi",CodiceFiscale="ABB"}), 4 new Documento ("1",new Cliente {Nome="Giuseppe",Cognome ="Rossi",CodiceFiscale="ABC"}), 5 new Documento ("1",new Cliente {Nome="Gabriele",Cognome ="Bianchi",CodiceFiscale="ABD"})};

Supponiamo di voler utilizzare una query expression per ottenere una lista (nello specifico un  oggetto che implementi l'interfaccia IEnumerable<T>, o IOrderedEnumerable<T> che estende IEnumerable<t>), che possa essere "esplorata" mediante uno statement foreach:

1 var result = 2 from d in documenti 3 orderby d.Numero 4 select d;

Eseguendo il tutto in un'applicazione console otterremmo:

image

Che non è proprio quello che ci aspettiamo dato che 2 viene prima di 10. Il problema nasce dal fatto che nel nostro modello ad oggetti, abbiamo definito il campo Numero, della classe Documento, come String. A questo punto potremmo optare tra almeno due soluzioni: procediamo con un refactoring del codice e cambiamo il tipo del membro Numero, o utilizziamo un overload dell'Extension Method OrderBy (o OrderByDescending). Più precisamente, utilizzeremo l'overload  seguente:

1 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>( 2 this IEnumerable<TSource> source, 3 Func<TSource, TKey> keySelector, 4 IComparer<TKey> comparer 5 ) 6

Il quale esegue l'ordinamento  ascendente di una sequenza di dati utilizzando uno specifico Comparer. Nello specifico, questo sarà così definito:

1 public class DocumentoComparer : IComparer<Documento> 2 { 3 #region IComparer<Documento> Members 4 5 public int Compare(Documento x, Documento y) 6 { 7 if (x.Numero.Equals(y.Numero)) 8 { 9 //Ordina in base al nominativo del cliente 10 return string.Compare(x.Cliente.Cognome, y.Cliente.Cognome); 11 } 12 else 13 { 14 if (int.Parse(x.Numero) < int.Parse(y.Numero)) 15 return -1; 16 else 17 return 1; 18 } 19 } 20 21 #endregion 22 }

Nel caso in cui siano presenti due documenti con lo stesso numero, magari perchè di tipo diverso, l'ordinamento viene effettuato in base all'ordinamento lessicografico della proprietà Cognome del Cliente, altrimenti le stringhe Numero sono convertite nei rispettivi valori interi, quindi eseguito il confronto.

A questo punto, mediante method syntax, possiamo scrivere:

1 var resultMethod = 2 documenti 3 .OrderBy(d => d, new DocumentoComparer());

Ottenendo:

image 

Nel caso in cui non sia fornito un comparatore o che Comparer sia nullo verrà utilizzata la proprietà Default, di Comparer<T>, ovvero Comparer<TKey>.Default, ma se il tipo T (come ad esempio Documento) non implementa ne l'interfaccia IComparable<T> ne IComparable, in fase di esecuzione verrà generata un'eccezione.

posted @ venerdì 2 gennaio 2009 19.58 | Feedback (0)
News

View Pietro Libro's profile on LinkedIn

DomusDotNet
   DomusDotNet

Pietro Libro