日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CallContext和多线程

發布時間:2025/6/17 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CallContext和多线程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  前一段時間正好要在某個網頁程序上開一個多線程調用多個組件的嘗試,這些組件是有其他團隊開發的(如:印度/俄羅斯),所以修改它們的代碼看起來是不太現實的,但是,令人惱火的是他們的代碼中大量的用到了AppContext.Current這個對象(實際上是用了HttpContext.Current.Item來存儲的),而一旦異步,HttpContext.Current就不復存在,自然就會不停的報出空引用異常,看起來異步是不太現實的了。

  就在無計可施的時候,突然發現有一個叫CallContext的奇怪的類,藏匿在System.Runtime.Remoting.Messaging這個幾乎沒人用的namespace下面,當然一開始我僅僅是被它的名稱所吸引,直譯過來不就是調用上下文嗎?感覺這個東西能有點作用。于是查閱了msdn,描述如下:

提供與執行代碼路徑一起傳送的屬性集。無法繼承此類。

  一句廢話。。。看備注吧:

CallContext 是類似于方法調用的線程本地存儲區的專用集合對象,并提供對每個邏輯執行線程都唯一的數據槽。數據槽不在其他邏輯線程上的調用上下文之間共享。當 CallContext 沿執行代碼路徑往返傳播并且由該路徑中的各個對象檢查時,可將對象添加到其中。

當對另一個 AppDomain 中的對象進行遠程方法調用時,CallContext 類將生成一個與該遠程調用一起傳播的 LogicalCallContext 實例。只有公開 ILogicalThreadAffinative 接口并存儲在 CallContext 中的對象被在 LogicalCallContext 中傳播到 AppDomain 外部。不支持此接口的對象不在 LogicalCallContext 實例中與遠程方法調用一起傳輸。

  似乎有那么點意思,不過邏輯線程的定義似乎有那么點模棱兩可,不過,也提到了一個接口ILogicalThreadAffinative,再看看這個接口定義了什么,一看成員定義。。。沒有成員。。。一個空接口,汗了一把,還是看看msdn上如何描述的吧:

標記可以在 LogicalCallContext 中傳播到 AppDomain 外部的對象。

  強調了在remoting中的作用,再看看備注:

當對另一個 AppDomain 中的對象進行遠程方法調用時,當前的 CallContext 類生成一個將與該調用一起傳播到遠程位置的 LogicalCallContext。只有公開 ILogicalThreadAffinative 接口并存儲在 CallContext 中的對象被傳播到 AppDomain 外部。不支持此接口的對象不在 LogicalCallContext 實例中與遠程方法調用一起傳輸。

  也是強調在remoting中的作用,但是可以想象,基本上是CallContext中用了類似is ILogicalThreadAffinative的方式,來區別對待不同的對象,對于符合這個接口的將被放到LogicalCallContext,而不符合的另外處理。

  從文檔角度,似乎已經沒有什么進展了,這時候,突然想起來一個以前看過的很有趣的類型ExecutionContext,namespace是System.Threading,看起來就是多線程準備的,不過,msdn上的例子就說了如何控制傳遞權限對象的問題,并沒有說到如何傳遞普通對象。

  一時想到所謂的LogicalCallContext會不會在ExecutionContext中存在哪?查了一下msdn,看到備注:

ExecutionContext 類為與執行的邏輯線程相關的所有信息提供單個容器。這包括安全上下文、調用上下文和同步上下文。

ExecutionContext 類提供的功能讓戶代碼可以在用戶定義的異步點之間捕獲和傳輸此上下文。公共語言運行庫確保在托管進程內運行庫定義的異步點之間一致地傳輸 ExecutionContext。

執行上下文是 COM 單元的托管等效項。在應用程序域中,每當傳輸線程時都必須傳輸整個執行上下文。在由 Thread..::.Start 方法、大多數線程池操作和通過 Windows 消息泵進行的 Windows 窗體線程封送處理所導致的傳輸過程中,將會出現這種情況。在不安全的線程池操作(如 UnsafeQueueUserWorkItem 方法)中不會出現這種情況,原因是不安全的線程池操作不會傳輸壓縮堆棧。每當壓縮堆棧流動時,托管的主體、同步、區域設置和用戶上下文也隨之流動。ExecutionContext 類提供 Capture 和 CreateCopy 方法以獲取執行上下文,并提供 Run 方法以設置當前線程的執行上下文。

與某個線程相關聯的 ExecutionContext 無法在另一個線程上進行設置。嘗試這樣做會導致引發異常。若要將 ExecutionContext 從一個線程傳播到另一個線程,請制作 ExecutionContext 的副本。

ExecutionContext 在內部存儲與 LogicalCallContext 相關聯的所有數據。這使得可以在復制和傳輸 ExecutionContext 時傳播 LogicalCallContext 數據。

  果然,ExecutionContext中有LogicalCallContext的數據,并且很好的說明了,無論是Thread.Start還是用線程池大多數操作,ExecutionContext都會自動將這些數據傳遞給那些線程(關于ThreadPool.UnsafeQueueUerWorkItem方法相信用的人應該不多),看起來演員們都到齊了,馬上可以演出一場多線程的好戲了。

  首先是起著關鍵作用ExectionContext,也許我們的代碼中沒必要出現它的身影,但是那僅僅是因為.net類庫的方法,為我們很好封裝了這個功能,沒有它,想在一個線程中把一個對象告訴另一個線程,就只有通過堆了。

  其次,LogicalCallContext,在眾多ExecutionContext傳播的對象中,很多是我們無法簡單的利用的(總不能為了傳播一個對象,去定義一個自定義的權限吧),而LogicalCallContext就是自定義對象的最好的載體。

  最后,剩下的問題就是如何讀寫這個LogicalCallContext的問題了,也就是終于輪到CallContext出場了。看一下CallContext為我們準備了些什么方法:GetData, SetData, LogicalGetData, LogicalSetData, FreeNamedDataSlot, GetHeader, SetHeader以及HostContext屬性。

  第一焦點,當然是GetData和SetData這兩個方法,做了個簡單的測試,發現這兩個方法,確實就是通過ILogicalThreadAffinative接口來決定是否要把對象發給新線程的,而刪除這個數據的方法就是FreeNamedDataSlot,現在只要為每一個要在多線程中共用的對象加上一個空接口,并且在多線程開始前在主線程中把對象設置進去,然后在其他線程中再取出來就可以把問題搞定了。多線程部分結束后,不要忘記用FreeNamedDataSlot去刪除一下。

  不知道大家注意到沒有,出了GetData和SetData外,還有一對LogicalGetData和LogicalSetData,這兩個是干什么用的哪?是不是和LogicalCallContext的Logical有什么關系哪?

  又把前面的那個簡單的實驗做了一下,只不過用了LogicalGetData和LogicalSetData這兩個方法,結論是無論是否實現ILogicalThreadAffinative接口,對象都可以在新線程內被訪問到,也就是說現在可以傳播任何數據給新線程,包括.net定義的string,int等基礎類型,這個方案已經接近完美了。

  回過頭來看看我的任務吧,只需要修改AppContext.Current屬性的實現,并且在多線程開始之前和之后做一個小小的處理,其他的組件就可以原封不動的并發的跑在各自的線程上。

  工作上的事情就到此為止了。

  在來說說CallContext.HostContext屬性是干什么的,經過簡單的測試,發現在Asp.net程序中,這個HostContext里面放的就是HttpContext的實例,ms也夠偷懶的。其實ms只要做一個很小的修改,Asp.net的多線程就不用這么麻煩了,只需要HttpContext實現一下ILogicalThreadAffinative接口,無論新開多少個線程,到那邊都能訪問到HttpContext.Current了,當然ms沒有這么做也是有原因的,一旦HttpContext被傳播到其他線程,那么asp.net就很難控制HttpContext對象的生命周期,而HttpContext對象又引用這HttpRequest對象,帶來的副作用可能要比想象的大得多。

轉載于:https://www.cnblogs.com/vwxyzh/archive/2009/02/21/1395416.html

總結

以上是生活随笔為你收集整理的CallContext和多线程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。