C 多執行緒之旅 3

2021-08-01 20:18:45 字數 4520 閱讀 4464

閱讀目錄

一、介紹

二、通過tpl進入執行緒池

三、不用tpl進入到執行緒池

v部落格前言

先交代下背景,寫《c#多執行緒之旅》這個系列文章主要是因為以下幾個原因:1.多執行緒在c/s和b/s架構中用得是非常多的;2.而且多執行緒的使用是非常複雜的,如果沒有用好,容易造成很多問題。

v寫在前面

多執行緒,有利也有弊,使用需謹慎。

v正文開始

c#多執行緒之旅(1)——介紹和基本概念

c#多執行緒之旅(2)——建立和開始執行緒

c#多執行緒之旅(3)——執行緒池

c#多執行緒之旅(4)——apm初探

c#多執行緒之旅(5)——同步機制介紹

c#多執行緒之旅(6)——詳解多執行緒中的鎖

c#多執行緒之旅(3)——執行緒池

回到頂部

thread__cnblogs_jackson0714.zip

第一篇~第三篇的**示例:

回到頂部

無論你什麼時候開始乙個執行緒,幾百毫秒會花在整理乙個新的local variable stack。每乙個執行緒缺省會消耗1mb的記憶體。執行緒池通過分享和**執行緒來削減這些開銷,允許多執行緒被應用在乙個非常顆粒級的級別而沒有效能損失。當充分利用多核系統去執行密集型計算的並行**時這是非常有用的。

下面是幾種方式進入執行緒池:

通過task parallel library(.net 4.0)

通過呼叫threadpool.queueuserworkitem

通過asynchronous delegates

通過backgroundworkder

下面的結構直接使用執行緒池:

system.timers.timer and system.threading.timer

framework methods 由async結束,比如webclient(the event-based asynchronous pattern)和大部分的begin***方法(the asynchronous programming model pattern)

plinq

task parallel library(tpl)和plinq是充分有效的和高等級的,甚至當執行緒池是不重要的時候,你也會想使用它們去協助處理多執行緒。

當使用執行緒池時需要注意下面的事情:

你不能設定乙個執行緒的名字,因為設定執行緒的名字將會使除錯更困難(當你在vs執行緒視窗中除錯時,即使你可以附加乙個描述)。

執行緒池中的執行緒總是後台執行緒(這通常不是問題)。

在應用程式的開始期間,阻塞乙個執行緒可能會觸發乙個延遲,除非你呼叫threadpool.setminthreads

你不能任意地改變池中的執行緒的優先順序-因為當它釋放會池中的時候,優先順序會被還原為正常狀態。

你可以通過屬性thread.currentthread.isthreadpoolthread的屬性查詢執行緒是否是正在執行的乙個池中的執行緒

回到頂部

你可以使用在taskparallel library中的task類來輕鬆的進入執行緒池。這個task類在framework 4.0中有介紹:如果你對老的結構比較熟悉,考慮用非泛型的task類替換threadpool.queueuserworkitem,將asunchoronousdelgates替換為泛型task。最新的結構速度更快,更方便,而且更複雜。

為了使用非泛型的任務類,呼叫task.factory.startnew方法,將方法傳進委託中。

task.factory.startnew會返回乙個task物件,你可以使用它去監控這個task,比如,你可以呼叫它的wait方法等待它直到它完成。

static void main(string args)

static void go()

當你呼叫task的wait方法時,乙個未處理的異常會很容易地重新丟擲到宿主執行緒上。(如果你不呼叫wait方法而是放棄這個task,乙個未處理的異常將會關閉掉這個程序)

泛型task類是非泛型task的子類。它讓你從這個已經完成執行的task中得到乙個返回值。在下面的例子中,我們使用task

static void main(string args)

static string downloadstring(string uri)

}

task parallel library有許多的功能,特別是提公升多核處理器的效能。我們會在並行程式設計中繼續討論tpl。

回到頂部

如果你的應用程式是.net framework的早期版本(4.0之前的版本),你將不能使用tpl。你必須使用老的結構進入執行緒池:

threadpool.queueuserworkitemasynchoronousdelegates.兩者的不同點是asynchronousdelegates讓你從執行緒那裡返回資料。asynchronousdelegates收集任何exception返回給呼叫者。

要使用queueuserworkitem

static void main(string args)

static void go(object data)

我們的目標方法go,必須接收乙個簡單object型別的引數(為了滿足waitcallback委託)。這將提供乙個簡單的方式傳遞資料到方法中,就像是parameterizedthreadstart。不像task,queueuserworkitem不會返回乙個物件去幫助你之後管理執行。還有,你必須顯式在目標方法的**中寫處理異常的**-因為未處理的異常將會終止程式。

threadpool.queueuserworkitem沒有提供從乙個已經完成的執行緒中得到它的返回值的機制。asynchronousdelegate invocations(asynchronous delegates for short)解決了這個問題,允許任何個數型別化的引數在兩個方向傳遞。此外,在asynchronous delegates上未處理的異常很方便地在原始執行緒上重新丟擲(更準確地說,這個執行緒叫做endinvoke),因此不需要顯示處理。

不要混淆asynchronous delegates和asynchronous method(方法以begin和end開頭的,比如file.beginread/file.endread)。asynchronous methods表面上按照簡單的協議,但是它們的存在是為了解決乙個更困難的問題。

下面是怎樣通過乙個asynchronous delegate開始乙個worker task:

例項化乙個委託,該委託針對你想要並行執行的method(典型的是預定義func delegates其中的一種)。

在delegate上呼叫begininvoke,儲存它的iasyncresult返回值。begininvoke立即返回給呼叫者。當其他池中的執行緒正在執行的時候,你可以執行其他動作。

當你需要這個結果,在delegate上呼叫endinvoke,傳遞已儲存的iasyncresult物件。

在下面的例子中,我們使用乙個asynchronous delegate invocation執行乙個與主線程同時執行的簡單方法,這個方法返回乙個字串的長度:

static void main(string args)

static int go(string messsage)

endinvoke做三件事情。第一,如果asynchronous delegate沒有完成執行,則一直等待它完成。第二,接收返回值(以及任何ref或者out引數)。第三,返回任何未處理的執行緒異常給呼叫它的執行緒。

當你呼叫begininvoke方法時,可以指定乙個call back delegate-乙個可以接收乙個iasyncresult 物件的方法,它會在委託方法完成後被自動呼叫這個允許正在發動的執行緒忘記asynchronous delegate,但它在call back結束時需要一點額外的工作。

v寫在最後

執行緒池的使用的提公升還沒有寫,最近兩年作息不規律,程式設計師得養好身體,早睡早起,睡覺睡覺。希望這篇部落格能幫到大家,希望得到園友們的支援!

作  者:jackson0714出  處:

一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!         

C 多執行緒之旅 7 終止執行緒

先交代下背景,寫 c 多執行緒之旅 這個系列文章主要是因為以下幾個原因 1.多執行緒在c s和b s架構中用得是非常多的 2.而且多執行緒的使用是非常複雜的,如果沒有用好,容易造成很多問題。c 多執行緒之旅目錄 c 多執行緒之旅 1 介紹和基本概念 c 多執行緒之旅 2 建立和開始執行緒 c 多執行...

Java多執行緒之旅 一

public class subthread extends thread public class subthreadtest public class runnableexample01 implements runnable public class runnableexample01test...

C 多執行緒之旅實戰 自旋鎖那點事

ticket lock clh lock mcs lock 總結前一篇文章講的是帶鎖的併發資料結構,而且講到了如果不帶鎖將會面臨什麼樣的問題。這一部分我將為大家帶來乙個全新的資料結構 自旋鎖。這是一種不使用阻塞庫的資料結構,我們將不使用阻塞庫的結構稱為非阻塞,但是不是所有的非阻塞資料結構都是無鎖的。...