国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

簡單看看ThreadPool的源碼以及從中看出線程間傳值的另一種方法

2019-11-14 16:21:12
字體:
供稿:網(wǎng)友

 

   這幾天太忙沒時間寫博客,今天回家就簡單的看了下ThreadPool的源碼,發(fā)現(xiàn)有一個好玩的東西,叫做”執(zhí)行上下文“,拽名叫做:”ExecutionContext“。

 

一:ThreadPool的大概流程。

 

第一步:它會調(diào)用底層一個helper方法。

 

第二步:走進(jìn)這個helper方法,我們會發(fā)現(xiàn)有一個隊列,并且這個隊列的item必須是QueueUserWorkItemCallback的實(shí)例,然后這就激發(fā)了我的

           興趣,看看QueueUserWorkItemCallback到底都有些什么?

 

第三步:走到QueueUserWorkItemCallback實(shí)例的時候,會依次把callback,state參數(shù)給當(dāng)前類的字段,并且有一個好玩的地方的就是根據(jù)

     ExecutionContext.IsFlowSupPRessed()來判斷要不要把”當(dāng)前線程的上下文“給”調(diào)用線程“?這個放在后面講,然后我們看到了一

    個 IThreadPoolWorkItem.ExecuteWorkItem()方法,里面有ContextCallback委托的調(diào)用,也許這個就是隊列中每一項中要調(diào)用

    的方法。

 

第四步:然后我們再回到第二步中的 ThreadPoolGlobals.workQueue.Enqueue(callback, true)方法進(jìn)去看看,并且我們的callback,state都被封裝成了

      QueueUserWorkItemCallback放到隊列中了,從這個Enqueue方法中,我們看到了一個this.EnsureThreadRequested(),走到方法里面去了

    之后,這時候急迫想去看ThreadPool.RequestWorkerThread()方法,但它是個extern方法,不過從名字上看就是請求工作線程去執(zhí)行,所以并

    沒有真實(shí)的發(fā)現(xiàn)到所謂的線程池這個東西。(由于不能窺全貌,可能有些說的不太對)

 

好了,上面的剖析大概就這樣了,其實(shí)所有的方法都封裝成了底層的一個類放在一個隊列中,應(yīng)該是用上面的for來挑選空閑的工作線程去執(zhí)行我們

的任務(wù),里面還有很多代碼,比較復(fù)雜,一時也看不懂什么。

 

二:執(zhí)行上下文

  剛才第三步說到了”執(zhí)行上下文“,看到這個方法里面有一個if條件,然后看到有一個 ExecutionContext.IsFlowSuppressed()方法,從名字上

就可以看出叫”阻止流動“,如果為否的話,就用Capture來抓當(dāng)前線程的”上下文信息“,然后我們就順藤摸瓜的往下看,從這個方法來看,我們依次

去抓取調(diào)用線程的”安全設(shè)置“,”宿主設(shè)置“,”同步信息“,“邏輯調(diào)用”,并且可以看到logicalCallContext有值的話,會做一個copy的操作。

 

其實(shí)這個logicalCallContext非常有意思,里面是一個KV結(jié)構(gòu),源碼里面也說了,只要我不IsFlowSuppressed,那么主線程的上下文會flow到

工作線程,那么logicalCallContext怎么設(shè)置呢?其實(shí)在C#里面的CallContext里面的LogicalSetData和LogicalGetData就可以做這些事情。

 1     class Program 2     { 3         static void Main(string[] args) 4         { 5             CallContext.LogicalSetData("name", "ctrip"); 6  7             Thread.CurrentThread.IsBackground = true; 8  9             ThreadPool.QueueUserWorkItem((o) =>10             {11                 var t = Thread.CurrentThread.ManagedThreadId;12 13                 var result = CallContext.LogicalGetData("name");14 15                 Console.WriteLine("我是工作線程: Name:" + result);16 17             });18 19             Console.Read();20         }21     }

 

可以看到我在主線程設(shè)置的值被工作線程讀到了,是不是很有意思,給我們線程間傳值提供了另一種方法,剛才我們也看到,一旦IsFlowSuppressed

了,那么context就返回null,也就阻止了將logicCallContext的信息傳遞給工作線程,可以用ExecutionContext.SuppressFlow()做到,下面具體

看一看。

 1   class Program 2     { 3         static void Main(string[] args) 4         { 5             CallContext.LogicalSetData("name", "ctrip"); 6  7             //阻止logical數(shù)據(jù)流動 8             ExecutionContext.SuppressFlow(); 9 10             Thread.CurrentThread.IsBackground = true;11 12             ThreadPool.QueueUserWorkItem((o) =>13             {14                 var t = Thread.CurrentThread.ManagedThreadId;15 16                 var result = CallContext.LogicalGetData("name");17 18                 Console.WriteLine("我是工作線程: Name:" + result);19 20             });21 22             Console.Read();23         }24     }

 

現(xiàn)在結(jié)論也出來了,去Capture主線程的上下文是需要很多的代碼量,所以如果工作線程用不到主線程的這些信息,那么你應(yīng)該做到顯示關(guān)閉,這樣

對工作線程的性能來說有很大的好處。

 


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 柏乡县| 兰西县| 若尔盖县| 水城县| 英德市| 县级市| 武义县| 项城市| 临汾市| 兰西县| 永昌县| 光山县| 清镇市| 个旧市| 阜阳市| 灵山县| 和平县| 城固县| 行唐县| 寿光市| 栖霞市| 南雄市| 广水市| 肇源县| 双桥区| 阿拉尔市| 柳江县| 阿荣旗| 三亚市| 深水埗区| 图木舒克市| 河东区| 南丰县| 青神县| 金沙县| 精河县| 济南市| 通州区| 文水县| 长沙县| 长宁县|