C# { 系统线程线程睡眠(100); AllThreadsComplete=true; foreach(System.Threading.Thread WorkerThread in RunningThreads) { if(WorkerThread.IsAl

C# { 系统线程线程睡眠(100); AllThreadsComplete=true; foreach(System.Threading.Thread WorkerThread in RunningThreads) { if(WorkerThread.IsAl,c#,multithreading,C#,Multithreading,{ 系统线程线程睡眠(100); AllThreadsComplete=true; foreach(System.Threading.Thread WorkerThread in RunningThreads) { if(WorkerThread.IsAlive) { AllThreadsComplete=false; } } } 对于(int Longitude=0;LongitudeSize

{ 系统线程线程睡眠(100); AllThreadsComplete=true; foreach(System.Threading.Thread WorkerThread in RunningThreads) { if(WorkerThread.IsAlive) { AllThreadsComplete=false; } } } 对于(int Longitude=0;LongitudeSize0) { Samples=WorkQueue.Dequeue(); } } 返回样品; } 私有静态int QueueSize() { 锁定(SyncRootWorkQueue) { 返回WorkQueue.Count; } } 私有静态对象SyncRootOutputData=新对象(); 私有静态int[,]输出数据; 私有静态void SetOutputData(int经度、int晶格度、int SumSamples) { 锁定(SyncRootOutputData) { OutputData[经度,格度]=总和样本; } } 私有静态void ParallelSum() { 工作项样本工作项; int SummedResult; SamplesWorkItem=DeQueueWork(); while(SamplesWorkItem!=null) { SummedResult=0; foreach(SampleWorkItem.RainFallSamples中的int SampleValue) { SummedResult+=样本值; } SetOutputData(SampleWorkItem.Longitude、SampleWorkItem.latitude、SummedResult); SamplesWorkItem=DeQueueWork(); } } }
感谢您的全面回复。但是PLINQ在.NET 3.5或.NET 4.0之前的版本中可用吗?我问这个问题是因为由于框架的限制,我只能使用.NET3.5。实现Parallel.For比我们想象的要困难一些,因为它有非常酷的东西,可以在线程之间窃取任务,并使用户Win7用户模式线程(较低的开销)。但是,如果需要高PrF并行计算,但不喜欢自己编写框架,可以使用PPL(C++并行)和静态链接库来编写VS2010中的C++库,该库创建一个自带的DLL,然后使用NET35。
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

class Program
{

    static void AverageOfZ (
        double[] input, 
        double[] result,
        int x, 
        int y, 
        int z
        )
    {
        Debug.Assert(input.Length == x*y*z);
        Debug.Assert(result.Length == x*y);

        //Replace Parallel with Sequential to compare with non-parallel loop
        //Sequential.For(
        Parallel.For(
            0,
            x*y,
            i =>
                {
                    var begin = i*z;
                    var end = begin + z;
                    var sum = 0.0;

                    for (var iter = begin; iter < end; ++iter)
                    {
                        sum += input[iter];
                    }

                    result[i] = sum/z;
                });

    }

    static void Main(string[] args)
    {
        const int X = 64;
        const int Y = 64;
        const int Z = 64;
        const int Repetitions = 40000;

        var random = new Random(19740531);
        var samples = Enumerable.Range(0, X*Y*Z).Select(x => random.NextDouble()).ToArray();
        var result = new double[X*Y];

        var then = DateTime.Now;

        for (var iter = 0; iter < Repetitions; ++iter)
        {
            AverageOfZ(samples, result, X, Y, Z);
        }

        var diff = DateTime.Now - then;
        Console.WriteLine(
            "{0} samples processed {1} times in {2} seconds", 
            samples.Length,
            Repetitions,
            diff.TotalSeconds
            );

    }
}

static class Sequential
{
    public static void For(int from, int to, Action<int> action)
    {
        for (var iter = from; iter < to; ++iter)
        {
            action(iter);
        }
    }
}
public static class MultiThreadSumRainFall
{
    const int LongitudeSize = 64;
    const int LattitudeSize = 64;
    const int RainFallSamplesSize = 64;
    const int SampleMinValue = 0;
    const int SampleMaxValue = 1000;
    const int ThreadCount = 4;

    public static void SumRainfallAndOutputValues()
    {
        int[][][] SampleData;
        SampleData = GenerateSampleRainfallData();
        for (int Longitude = 0; Longitude < LongitudeSize; Longitude++)
        {
            for (int Lattitude = 0; Lattitude < LattitudeSize; Lattitude++)
            {
                QueueWork(new WorkItem(Longitude, Lattitude, SampleData[Longitude][Lattitude]));
            }
        }
        System.Threading.ThreadStart WorkThreadStart;
        System.Threading.Thread WorkThread;
        List<System.Threading.Thread> RunningThreads;
        WorkThreadStart = new System.Threading.ThreadStart(ParallelSum);
        int NumThreads;
        NumThreads = ThreadCount;
        if (ThreadCount < 1)
        {
            NumThreads = 1;
        }
        else if (NumThreads > (Environment.ProcessorCount + 1))
        {
            NumThreads = Environment.ProcessorCount + 1;
        }
        OutputData = new int[LongitudeSize, LattitudeSize];
        RunningThreads = new List<System.Threading.Thread>();
        for (int I = 0; I < NumThreads; I++)
        {
            WorkThread = new System.Threading.Thread(WorkThreadStart);
            WorkThread.Start();
            RunningThreads.Add(WorkThread);
        }
        bool AllThreadsComplete;
        AllThreadsComplete = false;
        while (!AllThreadsComplete)
        {
            System.Threading.Thread.Sleep(100);
            AllThreadsComplete = true;
            foreach (System.Threading.Thread WorkerThread in RunningThreads)
            {
                if (WorkerThread.IsAlive)
                {
                    AllThreadsComplete = false;
                }
            }
        }
        for (int Longitude = 0; Longitude < LongitudeSize; Longitude++)
        {
            for (int Lattitude = 0; Lattitude < LattitudeSize; Lattitude++)
            {
                Console.Write(string.Concat(OutputData[Longitude, Lattitude], @" "));
            }
            Console.WriteLine();
        }
    }

    private class WorkItem
    {
        public WorkItem(int _Longitude, int _Lattitude, int[] _RainFallSamples)
        {
            Longitude = _Longitude;
            Lattitude = _Lattitude;
            RainFallSamples = _RainFallSamples;
        }
        public int Longitude { get; set; }
        public int Lattitude { get; set; }
        public int[] RainFallSamples { get; set; }
    }

    public static int[][][] GenerateSampleRainfallData()
    {
        int[][][] Result;
        Random Rnd;
        Rnd = new Random();
        Result = new int[LongitudeSize][][];
        for(int Longitude = 0; Longitude < LongitudeSize; Longitude++)
        {
            Result[Longitude] = new int[LattitudeSize][];
            for (int Lattidude = 0; Lattidude < LattitudeSize; Lattidude++)
            {
                Result[Longitude][Lattidude] = new int[RainFallSamplesSize];
                for (int Sample = 0; Sample < RainFallSamplesSize; Sample++)
                {
                    Result[Longitude][Lattidude][Sample] = Rnd.Next(SampleMinValue, SampleMaxValue);
                }
            }
        }
        return Result;
    }

    private static object SyncRootWorkQueue = new object();
    private static Queue<WorkItem> WorkQueue = new Queue<WorkItem>();
    private static void QueueWork(WorkItem SamplesWorkItem)
    {
        lock(SyncRootWorkQueue)
        {
            WorkQueue.Enqueue(SamplesWorkItem);
        }
    }
    private static WorkItem DeQueueWork()
    {
        WorkItem Samples;
        Samples = null;
        lock (SyncRootWorkQueue)
        {
            if (WorkQueue.Count > 0)
            {
                Samples = WorkQueue.Dequeue();
            }
        }
        return Samples;
    }
    private static int QueueSize()
    {
        lock(SyncRootWorkQueue)
        {
            return WorkQueue.Count;
        }
    }

    private static object SyncRootOutputData = new object();
    private static int[,] OutputData;
    private static void SetOutputData(int Longitude, int Lattitude, int SumSamples)
    {
        lock(SyncRootOutputData)
        {
            OutputData[Longitude, Lattitude] = SumSamples;
        }
    }

    private static void ParallelSum()
    {
        WorkItem SamplesWorkItem;
        int SummedResult;
        SamplesWorkItem = DeQueueWork();
        while (SamplesWorkItem != null)
        {
            SummedResult = 0;
            foreach (int SampleValue in SamplesWorkItem.RainFallSamples)
            {
                SummedResult += SampleValue;
            }
            SetOutputData(SamplesWorkItem.Longitude, SamplesWorkItem.Lattitude, SummedResult);
            SamplesWorkItem = DeQueueWork();
        }
    }
}