是的,如果你很懶,如果你的執行任務(wù)比較短,如果你不想對線(xiàn)程做更精細的控制,那么把這些繁瑣的東西丟給線(xiàn)程池吧。
一:ThreadPool
好了,下面看看TheadPool下有哪些常用的方法。
1:GetMaxThreads,GetMinThreads
首先我們肯定好奇線(xiàn)程池到底給我們如何控制線(xiàn)程數,下面就具體的看一看。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 int workerThreads; 6 7 int completePortsThreads; 8 9 ThreadPool.GetMaxThreads(out workerThreads, out completePortsThreads);10 11 Console.WriteLine("線(xiàn)程池中最大的線(xiàn)程數{0},線(xiàn)程池中異步IO線(xiàn)程的最大數目{1}", workerThreads, completePortsThreads);12 13 ThreadPool.GetMinThreads(out workerThreads, out completePortsThreads);14 15 Console.WriteLine("線(xiàn)程池中最小的線(xiàn)程數{0},線(xiàn)程池中異步IO線(xiàn)程的最小數目{1}", workerThreads, completePortsThreads);16 }17 }

有的同學(xué)可能就要問(wèn),我可以將1023設置為10230嗎?那么就會(huì )有10230個(gè)線(xiàn)程幫我做事多好啊,其實(shí)不然。
①:我先前的文章也說(shuō)過(guò),線(xiàn)程很多的話(huà),線(xiàn)程調度就越頻繁,可能就會(huì )出現某個(gè)任務(wù)執行的時(shí)間比線(xiàn)程調度花費的時(shí)間短很多的尷尬局面。
②:我們要知道一個(gè)線(xiàn)程默認占用1M的堆??臻g,如果10230個(gè)線(xiàn)程將會(huì )占用差不多10G的內存空間,我想普通的電腦立馬罷工。
2:SetMaxTheads,SetMinThreads
當然,默認的線(xiàn)程設置只是一個(gè)參考,如果我們處于性能和實(shí)際情況確實(shí)需要修改也沒(méi)關(guān)系,framework也給我們提供了現成的方法。
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 int workerThreads;
6
7 int completePortsThreads;
8
9 ThreadPool.SetMaxThreads(100, 50);
10
11 ThreadPool.SetMinThreads(20, 10);
12
13 ThreadPool.GetMaxThreads(out workerThreads, out completePortsThreads);
14
15 Console.WriteLine("線(xiàn)程池中最大的線(xiàn)程數{0},線(xiàn)程池中異步IO線(xiàn)程的最大數目{1}\n", workerThreads, completePortsThreads);
16
17 ThreadPool.GetMinThreads(out workerThreads, out completePortsThreads);
18
19 Console.WriteLine("線(xiàn)程池中最小的線(xiàn)程數{0},線(xiàn)程池中異步IO線(xiàn)程的最小數目{1}\n", workerThreads, completePortsThreads);
20 }
21 }

3: QueueUserWorkItem
需要容納任務(wù)并執行的方法來(lái)了,該方法有一個(gè)WaitCallBack的委托,我們只需要把將要執行的任務(wù)丟給委托,CLR將會(huì )在線(xiàn)程池中調派空閑的
線(xiàn)程執行。
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(Run1);
Console.Read();
}
static void Run1(object obj)
{
Console.WriteLine("我是線(xiàn)程{0},我是線(xiàn)程池中的線(xiàn)程嗎? \n回答:{1}", Thread.CurrentThread.ManagedThreadId,
Thread.CurrentThread.IsThreadPoolThread);
}
}
}

可能我們也需要像普通的Thread一樣帶一些參數到工作線(xiàn)程中,QueueUserWorkItem的第二個(gè)重載版本解決了我們的問(wèn)題。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 ThreadPool.QueueUserWorkItem(Run1, "我是主線(xiàn)程"); 6 7 Console.Read(); 8 } 9 10 static void Run1(object obj)11 {12 Console.WriteLine(obj);13 }14 }
4:RegisterWaitForSingleObject
我們知道,如果我們把要執行的任務(wù)丟給線(xiàn)程池后,相當于把自己的命運寄托在別人的手上。
①:我們再也不能控制線(xiàn)程的優(yōu)先級了。
②:丟給線(xiàn)程池后,我們再也不能將要執行的任務(wù)取消了。
是的,給別人就要遵守別人的游戲規則,不過(guò)RegisterWaitForSingleObject提供了一些簡(jiǎn)單的線(xiàn)程間交互,因為該方法的第一個(gè)參數是
WaitHandle,在VS對象瀏覽器中,我們發(fā)現EventWaitHandle繼承了WaitHandle,而ManualResetEvent和AutoResetEvent都繼承于
EventWaitHandle,也就是說(shuō)我們可以在RegisterWaitForSingleObject溶于信號量的概念。
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 AutoResetEvent ar = new AutoResetEvent(false);
6
7 ThreadPool.RegisterWaitForSingleObject(ar, Run1, null, Timeout.Infinite, false);
8
9 Console.WriteLine("時(shí)間:{0} 工作線(xiàn)程請注意,您需要等待5s才能執行。\n", DateTime.Now);
10
11 //5s
12 Thread.Sleep(5000);
13
14 ar.Set();
15
16 Console.WriteLine("時(shí)間:{0} 工作線(xiàn)程已執行。\n", DateTime.Now);
17
18 Console.Read();
19 }
20
21 static void Run1(object obj, bool sign)
22 {
23 Console.WriteLine("當前時(shí)間:{0} 我是線(xiàn)程{1}\n", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
24 }
25 }

我們知道在Threading下面有一個(gè)Timer計時(shí)器,當定期觸發(fā)任務(wù)的時(shí)候都是由線(xiàn)程池提供并給予執行,那么這里我們溶于信號量的概念以后同樣
可以實(shí)現計時(shí)器的功能。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 AutoResetEvent ar = new AutoResetEvent(false); 6 7 //參數2000:其實(shí)就是WaitOne(2000),采取超時(shí)機制 8 ThreadPool.RegisterWaitForSingleObject(ar, Run1, null, 2000, false); 9 10 Console.Read();11 }12 13 static void Run1(object obj, bool sign)14 {15 Console.WriteLine("當前時(shí)間:{0} 我是線(xiàn)程{1}\n", DateTime.Now, Thread.CurrentThread.ManagedThreadId);16 }17 }18 }

有時(shí)候,跑著(zhù)跑著(zhù)我們需要在某個(gè)時(shí)刻停止它,沒(méi)關(guān)系,RegisterWaitForSingleObject返回一個(gè)RegisteredWaitHandle類(lèi),那么我們就通過(guò)
RegisteredWaitHandle來(lái)動(dòng)態(tài)的控制,比如說(shuō)停止計數器的運行。
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 RegisteredWaitHandle handle = null;
6
7 AutoResetEvent ar = new AutoResetEvent(false);
8
9 handle = ThreadPool.RegisterWaitForSingleObject(ar, Run1, null, 2000, false);
10
11 //10s后停止
12 Thread.Sleep(10000);
13
14 handle.Unregister(ar);
15
16 Console.WriteLine("小子,主線(xiàn)程要干掉你了。");
17
18 Console.Read();
19 }
20
21 static void Run1(object obj, bool sign)
22 {
23 Console.WriteLine("當前時(shí)間:{0} 我是線(xiàn)程{1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
24 }
25 }

聯(lián)系客服