多线程计算超大数组辅助类

1 /// <summary>
2 /// 多线程计算大数组之和的类
3 /// </summary>
4 class CalculateBigArray
5 {
6 //比如数组有10000个元素,将这10000个分成100组,每组100个,各自对这一百个进行计算,左后在进行总和。
7 private int _size;
8 private int[] _bigArray;
9 private int[][] _breakArray;
10 private long[] _sumArray;
11 private AutoResetEvent[] _autoArray;
12 public delegate long CalDelegate(int[] array, int index);
13 public CalculateBigArray(int []bigArray,int size)
14 {
15 //初始化信号量
16 _autoArray = new AutoResetEvent[bigArray.Length/size];
17 for (int i = 0; i < bigArray.Length / size; i++)
18 {
19 _autoArray[i] = new AutoResetEvent(false);
20 }
21 //初始化其他私有变量
22 _size = size;
23 _bigArray = bigArray;
24 _sumArray = new long[bigArray.Length / size];
25 _breakArray = null;
26 }
27
28 /// <summary>
29 /// 将大数组进行分解,分解成一个二维数组
30 /// </summary>
31 private void BreakBigArray()
32 {
33 _breakArray = new int[_bigArray.Length / _size][];
34 int temp = 0;
35 for (int i = 0; i < _bigArray.Length / _size; i++)
36 {
37 temp = _size * i;
38 _breakArray[i] = new int[100];
39 for (int j = 0; j < 100; j++)
40 {
41 _breakArray[i][j] = _bigArray[temp + j];
42 }
43 }
44 }
45
46 private long CalPerUnit(int []array,int index)
47 {
48 long sum = 0;
49 foreach (int item in array)
50 {
51 sum += item;
52 }
53 //Thread.Sleep(30);
54 _autoArray[index].Set();
55 return sum;
56 }
57
58 private long CalSum()
59 {
60 long sum = 0;
61 if (_bigArray.Length / _size < 2 || _bigArray.Length / _size > 64)
62 {
63 throw new Exception("数组的长度过长,请加大因子");
64 }
65 WaitHandle.WaitAll(_autoArray);
66 foreach (var item in _sumArray)
67 {
68 sum += item;
69 }
70 return sum;
71 }
72
73 public long AsyncCal()
74 {
75 //如果还没有分解数组,则进行数据的分解。
76 if (_breakArray==null)
77 {
78 this.BreakBigArray();
79 }
80 CalculateBigArray.CalDelegate calDelete = null;
81 for (int i = 0; i < _bigArray.Length/_size; i++)
82 {
83 calDelete=new CalculateBigArray.CalDelegate(this.CalPerUnit);
84 IAsyncResult result=calDelete.BeginInvoke(_breakArray[i], i, null, null);
85 //将计算的结果存入数组
86 _sumArray[i] = calDelete.EndInvoke(result);
87 }
88 //Thread.Sleep(5000);
89 //这里会不会出现这种情况,假如计算最后一个子数组的线程还没有执行完毕,就进行this.CalSum(),这就会造成死锁
90 return this.CalSum();
91 }
92 }

1.这只是雏形,还要增加减法,乘法。

2.在调用this.CalSum()时假如计算最后一个子数组的线程还没有执行完毕,就进行this.CalSum(),这就会造成死锁,待验证?

解答:上面的推断是错误的,在调用BeginInvoke之后,可以随时调用EndInvoke,而一旦调用了EndInvoke,若异步线程还没有终止,则会阻塞调用线程,知道异步线程完成操作。因此不能造成上面所说的死锁。 但是如果是使用回调的方法实现总和的计算要注意,回调的方法是运行在ThreadPool上面的。MSDN上面的原话是这样的:

回调在 ThreadPool 线程上执行。 ThreadPool 线程是后台线程,这些线程不会在主线程结束后保持应用程序的运行,因此示例的主线程必须休眠足够长的时间以便回调完成。

总结:在.NET下使用多线程进行编程的时候,由于ThreadStart委托是无返回值,无参数的,因此对于需要用多线程实现某些辅助方法时,如果此方法有参数,则不能用最原始的

Thread thread=new Thread(ThreadStrat(Func));在没有返回值的情况下,可以利用线程池上的ThreadPool.QueueUserWorkItem(new WaitCallback(callBack),object)

但是多个参数必须一起封装在一个class里面,在callBack函数里面进行类型转换。利用BeginInvoke是一个不错的解决方法。
   ThreadPool.QueueUserWorkItem(new WaitCallback(callBack),object);
   ThreadPool.QueueUserWorkItem(new WaitCallback(callBack),object);

posted @ 2011-02-22 17:58  雁北飞  阅读(571)  评论(0编辑  收藏  举报