线程池用法的改进
引用: http://blog.csdn.net/jhycjhyc/article/details/7243728
在MSDN关于使用线程池的一个例子(见http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80).aspx).程序如下:
1 public class Fibonacci 2 { 3 public int N { get { return _n; } } 4 private int _n; 5 6 public int FibOfN { get { return _fibOfN; } } 7 private int _fibOfN; 8 9 private ManualResetEvent _doneEvent; 10 11 public Fibonacci(int n, ManualResetEvent doneEvent) 12 { 13 _n = n; 14 _doneEvent = doneEvent; 15 } 16 17 // Wrapper method for use with thread pool. 18 public void ThreadPoolCallback(Object threadContext) 19 { 20 21 int threadIndex = (int)threadContext; 22 Console.WriteLine("thread {0} started...", threadIndex); 23 _fibOfN = Calculate(_n); 24 Console.WriteLine("thread {0} result calculated...", threadIndex); 25 _doneEvent.Set(); 26 } 27 28 // Recursive method that calculates the Nth Fibonacci number. 29 public int Calculate(int n) 30 { 31 //Thread thread = Thread.CurrentThread; 32 //Console.WriteLine("[{0}] Calculate:{1}...", thread.ManagedThreadId, n); 33 if (n <= 1) 34 { 35 return n; 36 } 37 return Calculate(n - 1) + Calculate(n - 2); 38 } 39 40 }
调用方法:
1 static void Main(string[] args) 2 { 3 const int FibonacciCalculations = 2; //最大只能64,超出会报错 4 5 // One event is used for each Fibonacci object 6 ManualResetEvent[] doneEvents = new ManualResetEvent[FibonacciCalculations]; 7 Fibonacci[] fibArray = new Fibonacci[FibonacciCalculations]; 8 Random r = new Random(); 9 10 // Configure and launch threads using ThreadPool: 11 Console.WriteLine("launching {0} tasks...", FibonacciCalculations); 12 for (int i = 0; i < FibonacciCalculations; i++) 13 { 14 doneEvents[i] = new ManualResetEvent(false); 15 Fibonacci f = new Fibonacci(r.Next(20, 40), doneEvents[i]); 16 fibArray[i] = f; 17 ThreadPool.QueueUserWorkItem(new WaitCallback(f.ThreadPoolCallback), i); 18 } 19 20 // Wait for all threads in pool to calculation... 21 WaitHandle.WaitAll(doneEvents); 22 Console.WriteLine("All calculations are complete."); 23 24 // Display the results... 25 for (int i = 0; i < FibonacciCalculations; i++) 26 { 27 Fibonacci f = fibArray[i]; 28 Console.WriteLine("Fibonacci({0}) = {1}", f.N, f.FibOfN); 29 } 30 Console.ReadLine(); 31 }
以上例子是利用多线程的线程池技术进行批处理的经典范例,在实际应用中稍加改动就可以实现自己所需的功能,但遗憾的是,如果批处理的任务数大于64个时,程序运行就会出错,提示"WaitHandles 的数目必须少于或等于 64 个."以上例而言,将"const int FibonacciCalculations = 10;"改为"const int FibonacciCalculations = 65;"后再运行就会出错,这确实是一个不足,因为在实际工作中很多情况下需要用线程池技术批量处理64个以上的任务,怎么办呢?经过分析,对以上程序做了一些改动,解决了这个问题,而且程序的结构更简单,也不再需要使用 ManualResetEvent 对象,修改后的程序如下:
1 public class Fibonacci_02 2 { 3 public int ifdone = 0; //注意这里 4 5 public int N { get { return _n; } } 6 private int _n; 7 8 public int FibOfN { get { return _fibOfN; } } 9 private int _fibOfN; 10 11 public Fibonacci_02(int n) 12 { 13 _n = n; 14 } 15 16 // Wrapper method for use with thread pool. 17 public void ThreadPoolCallback(Object threadContext) 18 { 19 int threadIndex = (int)threadContext; 20 Console.WriteLine("thread {0} started...", threadIndex); 21 _fibOfN = Calculate(_n); 22 Console.WriteLine("thread {0} result calculated...", threadIndex); 23 24 ifdone = 1; 25 } 26 27 // Recursive method that calculates the Nth Fibonacci number. 28 public int Calculate(int n) 29 { 30 //Thread thread = Thread.CurrentThread; 31 //Console.WriteLine("[{0}] Calculate:{1}...", thread.ManagedThreadId, n); 32 if (n <= 1) 33 { 34 return n; 35 } 36 Thread.Sleep(1); 37 return Calculate(n - 1) + Calculate(n - 2); 38 } 39 }
调用方法:
1 static void Main(string[] args) 2 { 3 const int FibonacciCalculations = 2;//可以无限大 4 5 // One event is used for each Fibonacci object 6 Fibonacci_02[] fibArray = new Fibonacci_02[FibonacciCalculations]; 7 Random r = new Random(); 8 9 // Configure and launch threads using ThreadPool: 10 Console.WriteLine("launching {0} tasks...", FibonacciCalculations); 11 for (int i = 0; i < FibonacciCalculations; i++) 12 { 13 Fibonacci_02 f = new Fibonacci_02(r.Next(20, 40)); 14 fibArray[i] = f; 15 ThreadPool.QueueUserWorkItem(new WaitCallback(f.ThreadPoolCallback), i); 16 } 17 18 // Wait for all threads in pool to calculation... 19 //注意这里 20 while (true) 21 { 22 int counts = 0; 23 for (int i = 0; i < FibonacciCalculations; i++) counts = counts + fibArray[i].ifdone; 24 if (counts == FibonacciCalculations) break; 25 } 26 Console.WriteLine("All calculations are complete."); 27 28 // Display the results... 29 for (int i = 0; i < FibonacciCalculations; i++) 30 { 31 Fibonacci_02 f = fibArray[i]; 32 Console.WriteLine("Fibonacci({0}) = {1}", f.N, f.FibOfN); 33 } 34 Console.ReadLine(); 35 }