Alessandro Del Sole's Blog

{ A programming space about Microsoft® .NET® }
posts - 1909, comments - 2047, trackbacks - 352

My Links

News

Your host

This is me! Questo spazio è dedicato a Microsoft® .NET®, di cui sono molto appassionato :-)

Cookie e Privacy

Microsoft MVP

My MVP Profile

Microsoft Certified Professional

Microsoft Specialist

Xamarin Certified Mobile Developer

Il mio libro su VB 2015!

Pre-ordina il mio libro su VB 2015 Pre-ordina il mio libro "Visual Basic 2015 Unleashed". Clicca sulla copertina per informazioni!

Il mio libro su WPF 4.5.1!

Clicca sulla copertina per informazioni! E' uscito il mio libro "Programmare con WPF 4.5.1". Clicca sulla copertina per informazioni!

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.
If you're not an Italian user, please visit my English blog

Le vostre visite

I'm a VB!

Guarda la mia intervista a Seattle

Follow me on Twitter!

Altri spazi

GitHub
I miei progetti open-source su GitHub

Article Categories

Archives

Post Categories

Image Galleries

Privacy Policy

Mantenere l'ordine sequenziale delle query con Parallel LINQ

Una delle situazioni a cui bisogna fare attenzione quando si lavora con Parallel LINQ, è che i risultati delle query confluiscono in sequenze i cui elementi sono disposti "in ordine sparso". Ciò è del tutto normale, poiché lo stesso compito è suddiviso su più thread che vengono eseguiti contemporaneamente quindi non è possibile prevedere a priori un ordine sequenziale. Certamente ciò può costituire un problema nel momento in cui si ha necessità di scorrere una sequenza nell'ordine prefissato che ci si attenderebbe, ma fortunatamente la soluzione c'è.

Riprendiamo l'esempio di codice completo, scritto con VB 2010 Beta 1, del post introduttivo a PLINQ al quale vi rimando per i commenti al codice stesso:

Imports System.Threading

 

Module Module1

 

    Private Function IsOdd(ByVal number As Integer) As Boolean

 

        'Simulo un lavoro intensivo

        Thread.SpinWait(1000000)

        Return (number Mod 2) <> 0

    End Function

 

    Sub Main()

        Dim range = Enumerable.Range(0, 1000)

 

        Dim query = From num In range.AsParallel

                    Where (IsOdd(num))

                    Select num

 

        'Un contatore

        Dim sw As Stopwatch = Stopwatch.StartNew

 

        'La query LINQ viene effettivamente eseguita qui (metodo Count)

        Console.WriteLine("Elementi rilevati: " + query.Count.ToString)

        sw.Stop()

 

        Console.WriteLine(sw.ElapsedMilliseconds.ToString)

        Console.ReadLine()

    End Sub

End Module

Ora, se io andassi ad iterare il risultato ottenuto con un banalissimo ciclo di questo tipo:

        For Each n In query

            Console.WriteLine(n)

        Next

scoprirei che i numeri ottenuti non sono in ordine sequenziale dal più piccolo al più grande come potrei attendermi, bensì in ordine sparso, dovuto all'esecuzione di thread multipli. Per ovviare al problema, è sufficiente utilizzare il metodo extension AsOrdered che permette di trattare l'origine dati come se fosse una sequenza ordinata e che funziona esclusivamente dopo l'invocazione di AsParallel. Ciò premesso, è sufficiente sostituire il codice della clausola From con il seguente:

        'Aggiungo semplicemente AsOrdered

        Dim query = From num In range.AsParallel.AsOrdered

Per far sì che il risultato della query sia una sequenza di numeri ordinata dal più piccolo al più grande. Provare per credere :-)

Alessandro

Print | posted on mercoledì 9 settembre 2009 21:59 | Filed Under [ LINQ Parallel Programming ]

Powered by:
Powered By Subtext Powered By ASP.NET