Nasıl yapılır: İş Parçacığı Yerel Değişkenleriyle bir Parallel.For Döngüsü Yazma

Bu örnekte, döngü For tarafından oluşturulan her ayrı görevde durum depolamak ve almak için iş parçacığı yerel değişkenlerinin nasıl kullanılacağı gösterilmektedir. İş parçacığı yerel verilerini kullanarak, paylaşılan duruma çok sayıda erişimi eşitleme yükünden kaçınabilirsiniz. Her yinelemede paylaşılan bir kaynağa yazmak yerine, görevin tüm yinelemeleri tamamlanana kadar değeri hesaplar ve depolarsınız. Ardından son sonucu paylaşılan kaynağa bir kez yazabilir veya başka bir yönteme geçirebilirsiniz.

Örnek

Aşağıdaki örnek, bir milyon öğe içeren bir dizideki değerlerin toplamını hesaplamak için yöntemini çağırır For<TLocal>(Int32, Int32, Func<TLocal>, Func<Int32,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) . Her öğenin değeri kendi dizinine eşittir.

using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

class Test
{
    static void Main()
    {
        int[] nums = Enumerable.Range(0, 1_000_000).ToArray();
        long total = 0;

        // Use type parameter to make subtotal a long, not an int
        Parallel.For<long>(0, nums.Length, () => 0,
            (j, loop, subtotal) =>
            {
                subtotal += nums[j];
                return subtotal;
            },
            subtotal => Interlocked.Add(ref total, subtotal));

        Console.WriteLine("The total is {0:N0}", total);
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }
}
'How to: Write a Parallel.For Loop That Has Thread-Local Variables

Imports System.Threading
Imports System.Threading.Tasks

Module ForWithThreadLocal

    Sub Main()
        Dim nums As Integer() = Enumerable.Range(0, 1000000).ToArray()
        Dim total As Long = 0

        ' Use type parameter to make subtotal a Long type. Function will overflow otherwise.
        Parallel.For(Of Long)(0, nums.Length, Function() 0, Function(j, [loop], subtotal)
                                                                subtotal += nums(j)
                                                                Return subtotal
                                                            End Function, Function(subtotal) Interlocked.Add(total, subtotal))

        Console.WriteLine("The total is {0:N0}", total)
        Console.WriteLine("Press any key to exit")
        Console.ReadKey()
    End Sub

End Module

Her For yöntemin ilk iki parametresi, başlangıç ve bitiş yineleme değerlerini belirtir. yönteminin bu aşırı yüklemesinde, üçüncü parametre yerel durumunuzu başlatabileceğiniz yerdir. Bu bağlamda yerel durum, yaşam süresi geçerli iş parçacığındaki döngünün ilk yinelemesinden hemen öncesinden son yinelemeden hemen sonrasına kadar uzanan bir değişken anlamına gelir.

Üçüncü parametrenin türü, Func<TResult>TResult parçacığı yerel durumunu depolayacak değişkenin türüdür. Türü, genel yöntem çağrılırken sağlanan genel For<TLocal>(Int32, Int32, Func<TLocal>, Func<Int32,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) tür bağımsız değişkeni tarafından tanımlanır ve bu durumda olur Int64. tür bağımsız değişkeni derleyiciye iş parçacığı yerel durumunu depolamak için kullanılacak geçici değişkenin türünü bildirir. Bu örnekte, ifade () => 0 (veya Function() 0 Visual Basic'te) iş parçacığı yerel değişkenini sıfır olarak başlatır. Genel tür bağımsız değişkeni bir başvuru türü veya kullanıcı tanımlı değer türüyse, ifade şöyle görünür:

() => new MyClass()  
Function() new MyClass()  

Dördüncü parametre döngü mantığını tanımlar. İmzası C# veya Visual Basic'te olan Func<int, ParallelLoopState, long, long> bir temsilci veya Func(Of Integer, ParallelLoopState, Long, Long) lambda ifadesi olmalıdır. İlk parametre, döngünün bu yinelemesi için döngü sayacının değeridir. İkincisi, döngüden çıkmak için kullanılabilecek bir ParallelLoopState nesnedir; bu nesne sınıfı tarafından döngünün Parallel her oluşumuna sağlanır. Üçüncü parametre, iş parçacığı yerel değişkenidir. Son parametre dönüş türüdür. Bu durumda türün nedeni, tür bağımsız değişkeninde For belirttiğimiz tür olmasıdırInt64. Bu değişken adlandırılır subtotal ve lambda ifadesi tarafından döndürülür. Dönüş değeri, döngünün sonraki her yinelemesinde başlatmak subtotal için kullanılır. Bu son parametreyi, her yinelemeye geçirilen ve son yineleme tamamlandığında temsilciye localFinally geçirilen bir değer olarak da düşünebilirsiniz.

Beşinci parametre, belirli bir iş parçacığındaki tüm yinelemeler tamamlandıktan sonra bir kez çağrılan yöntemi tanımlar. Giriş bağımsız değişkeninin türü yine yöntemin tür bağımsız değişkenine For<TLocal>(Int32, Int32, Func<TLocal>, Func<Int32,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) ve gövde lambda ifadesi tarafından döndürülen türe karşılık gelir. Bu örnekte değer, yöntemini çağırarak Interlocked.Add sınıf kapsamındaki bir değişkene iş parçacığı güvenli bir şekilde eklenir. İş parçacığı yerel değişkenini kullanarak döngünün her yinelemesinde bu sınıf değişkenine yazmaktan kaçındık.

Lambda ifadelerini kullanma hakkında daha fazla bilgi için bkz . PLINQ ve TPL'de Lambda İfadeleri.

Ayrıca bkz.