技术开发 频道

直线出击!.NET 4.0并行计算深入解读

  那么我们上面的代码可以修改为,加了了ConcurrentQueue和ConcurrentStack的最基本的操作。

/// <summary>
        
/// 并行循环操作集合类,集合内只取5个对象
        
/// </summary>
        
private void Demo7()
        {
            ConcurrentQueue
<int> data = new ConcurrentQueue<int>();
            Parallel.For(
0, Program.Data.Count, (i) =>
            {
                
if (Program.Data[i] % 2 == 0)
                    data.Enqueue(Program.Data[i]);
//将对象加入到队列末尾
            });
            
int R;
            
while (data.TryDequeue(out R))//返回队列中开始处的对象
            {
                Console.WriteLine(R);
            }

            Console.WriteLine(
"执行完成For.");
        }

        
/// <summary>
        
/// 并行循环操作集合类
        
/// </summary>
        
private void Demo8()
        {
            ConcurrentStack
<int> data = new ConcurrentStack<int>();
            Parallel.ForEach(Program.Data, (i)
=>
            {
                
if (Program.Data[i] % 2 == 0)
                    data.Push(Program.Data[i]);
//将对象压入栈中
            });
            
int R;
            
while (data.TryPop(out R))//弹出栈顶对象
            {
                Console.WriteLine(R);
            }

            Console.WriteLine(
"执行完成ForEach.");
        }

 

  ok,这里返回一个序列的问题也解决了。

  结论3:在并行循环内重复操作的对象,必须要是thread-safe(线程安全)的。集合类的线程安全对象全部在System.Collections.Concurrent命名空间下。

  四、返回集合运算结果/含有局部变量的并行循环

  使用循环的时候经常也会用到迭代,那么在并行循环中叫做 含有局部变量的循环 。下面的代码中详细的解释,这里就不啰嗦了。

  /// <summary>
        
/// 具有线程局部变量的For循环
        
/// </summary>
        
private void Demo9()
        {
            List
<int> data = Program.Data;
            
long total = 0;

            
//这里定义返回值为long类型方便下面各个参数的解释
            Parallel.For
<long>(0,           // For循环的起点
                data.Count,                
// For循环的终点
                ()
=> 0,                    // 初始化局部变量的方法(long),既为下面的subtotal的初值
                (i, LoopState, subtotal)
=> // 为每个迭代调用一次的委托,i是当前索引,LoopState是循环状态,subtotal为局部变量名
                {
                    subtotal
+= data[i];    // 修改局部变量
                    return subtotal;        
// 传递参数给下一个迭代
                },
                (finalResult)
=> Interlocked.Add(ref total, finalResult) //对每个线程结果执行的最后操作,这里是将所有的结果相加
                );
            Console.WriteLine(total);
        }

        
/// <summary>
        
/// 具有线程局部变量的ForEach循环
        
/// </summary>
        
private void Demo10()
        {
            List
<int> data = Program.Data;
            
long total = 0;

            Parallel.ForEach
<int, long>(data, // 要循环的集合对象
                ()
=> 0,                      // 初始化局部变量的方法(long),既为下面的subtotal的初值
                (i, LoopState, subtotal)
=>   // 为每个迭代调用一次的委托,i是当前元素,LoopState是循环状态,subtotal为局部变量名
                {
                    subtotal
+= i;            // 修改局部变量
                    return subtotal;          
// 传递参数给下一个迭代
                },
                (finalResult)
=> Interlocked.Add(ref total, finalResult) //对每个线程结果执行的最后操作,这里是将所有的结果相加
                );

            Console.WriteLine(total);
        }

 

  结论4:并行循环中的迭代,确实很伤人。代码太难理解了。  

0
相关文章