C#的線程池使用起來還是非常簡單的,這里記錄一下。
根據http://blog.csdn.net/chen_zw/article/details/7939834里的描述這里記錄一下C#線程池的特點
- 一個進程有且只能管理一個線程池。
- 線程池線程都是后台線程(即不會阻止進程的停止)
- 每個線程都使用默認堆棧大小,以默認的優先級運行,並處於多線程單元中。超過最大值的其他線程需要排隊,但它們要等到其他線程完成后才啟動。
- 在CLR 2.0 SP1之前的版本中,線程池中 默認最大的線程數量 = 處理器數 * 25, CLR 2.0 SP1之后就變成了 默認最大線程數量 = 處理器數 * 250,線程上限可以改變,通過使用ThreadPool.GetMax+Threads和ThreadPool.SetMaxThreads方法,可以獲取和設置線程池的最大線程數。
- 默認情況下,每個處理器維持一個空閑線程,即默認最小線程數 = 處理器數。
- 當進程啟動時,線程池並不會自動創建。當第一次將回調方法排入隊列(比如調用ThreadPool.QueueUserWorkItem方法)時才會創建線程池。
- 在對一個工作項進行排隊之后將無法取消它。
- 線程池中線程在完成任務后並不會自動銷毀,它會以掛起的狀態返回線程池,如果應用程序再次向線程池發出請求,那么這個掛起的線程將激活並執行任務,而不會創建新線程,這將節約了很多開銷。只有線程達到最大線程數量,系統才會以一定的算法銷毀回收線程。
在使用線程池的時候,需要初始化其狀態
ManualResetEvent eventX = new ManualResetEvent(false);//表示線程池的狀態 false代表非終結狀態
根據https://www.cnblogs.com/tianboblog/p/5393444.html介紹:
當初始化為true時,為終止狀態
static
ManualResetEvent _mre =
new
ManualResetEvent(
true
);
當初始化為false時,為非終止狀態
static
ManualResetEvent _mre =
new
ManualResetEvent(
false
);
終止狀態時WaitOne()允許線程訪問下邊的語句
非終止狀態時WaitOne()阻塞線程,不允許線程訪問下邊的語句
把非終止狀態改為終止狀態用Set()方法
把終止狀態改為非終止狀態用Reset()方法
//按鈕事件
private void btnBatchSend_Click(object sender, RoutedEventArgs e)
{
eventX.Reset();
ThreadPool.SetMinThreads(1, 1);//設置線程池在新請求預測中維護的空閑線程數
ThreadPool.SetMaxThreads(10,10);//設置可以同時處於活動狀態的線程池的最大請求數目
以上兩句必須都有才行
//循環設置執行對象,
for (int i = 0; i < list.Count; i++)
{
ThreadPool.QueueUserWorkItem(tranSend, oj);//
}
eventX.WaitOne();//當是非終結狀態時,會阻塞主線程
eventX.Reset();//設置為非終結狀態
}
worker.RunWorkerCompleted += (o, ea) =>
{
//sb.Append("主線程執行完畢");
//this.txt_cansole.Text = sb.ToString();
this.btnBatchCheck.IsEnabled = true;
this.btnBatchSend.Visibility = Visibility.Visible;
this.btnStopSend.Visibility = Visibility.Collapsed;
};
this.btnBatchCheck.IsEnabled = false;
this.btnBatchSend.Visibility = Visibility.Collapsed;
this.btnStopSend.Visibility = Visibility.Visible;
worker.RunWorkerAsync();
//每個線程將會執行的任務
private void tranSend(object order)
{
Order s = order as Order;
//當是最后一個order 或者 用戶點了停止按鈕時
if (s.IsLas || Break)
{
eventX.Set();//當點了停止按鈕時,將線程池信號燈狀態設置為終結狀態這時會通知主線程繼續往下執行
return;
}
//真正的執行任務代碼
s.SendMessage = ">>";
s.ItemStatus = 1; /
}
可以看出來熟練C#線程池的使用主要是控制好信號燈的狀態,當主線程往下執行時,for循環里的代碼會很快執行完畢,雖然最多只允許了十個線程同時活動,但十個之后的對象已經加入了隊列,需要中斷時,需要在執行任務里去自行判斷。
if (s.IsLas || Break)
{
eventX.Set();//當點了停止按鈕時,將線程池信號燈狀態設置為終結狀態這時會通知主線程繼續往下執行
return;
}