1. 程式人生 > 實用技巧 >【譯】StackExchange.Redis 中文文件(十三)Thread Theft

【譯】StackExchange.Redis 中文文件(十三)Thread Theft

Thread Theft

如果你是因為異常中的連結來到這裡,並且你只想讓程式碼能正常執行,那麼只要在 application startup 裡新增以下程式碼:

ConnectionMultiplexer.SetFeatureFlag("preventthreadtheft", true);

看看是否能解決問題。如果您想了解更多有關此內容的資訊,請繼續閱讀!

什麼是 thread theft?

對於每個 redis 的連線,StackExchange.Redis 保留了我們已傳送給 redis 的等待答覆的命令佇列。隨著每個回覆的到來,我們檢視下一個掛起的命令(保留了順序,這使事情變得簡單),併為該回復觸發 "here's your result" API。 對於 async

/await 程式碼,這將導致 "continuation" 被重新啟用,這就是當 await 完成的任務完成後,程式碼恢復工作的方式。那是簡單的版本,但現實有些微妙。

預設情況下,當你在 Task 上觸發 TrySetResult 時,連續性將被同步呼叫。設定結果的執行緒現在可以立即繼續執行,無論你想要執行何種連續性。 在我們的示例中,那將是非常糟糕的,因為那將意味著專用的讀取器迴圈(這是要處理來自 redis 的結果)正在執行你的應用程式邏輯;這是 thread theft,並且會在資訊中顯示為帶有 rs: CompletePendingMessage 的大量超時(rs 是 the reader s

tate;你不應經常觀察 它在 CompletePendingMessage* 步驟中顯示,因為它的意思是非常快;如果你經常看到它,則可能意味著嘗試設定結果時劫持了 reader。

為了避免這種情況,我們使用 TaskCreationOptions.RunContinuationsAsynchronously 標誌。 它的作用在某種程度上取決於你是否具有 SynchronizationContext。 如果沒有(在控制檯應用程式,服務等中很常見),則 TPL 使用標準執行緒池機制來安排繼續。 如果有一個 SynchronizationContext (在UI應用程式和Web伺服器中很常見),則使用它的 Post

方法。 Post 方法意思著是一個非同步排程 API。 但是並非所有實現都是平等的。 一些 SynchronizationContext 實現將 Post 視為同步呼叫。 對於 LegacyAspNetSynchronizationContext 尤其如此,如果使用以下方法配置 ASP.NET,則會得到以下結果:

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="false" />

or

<httpRuntime targetFramework="4.5" />

(citation)

在這些情況下,我們將再次導致 reader 被盜並用於處理你的應用程式邏輯。這可能使任何進一步的等待超時(無論是暫時的(直到應用程式邏輯選擇釋放執行緒),還是永久的(本質上使自己陷入僵局))都註定要失敗。

為避免這種情況,本類庫增加了一層懷疑;具體來說,如果啟用了 preventthreadtheft 功能標誌,我們將搶先地完成執行緒池中的任務佇列。 這在預設情況下效率較低,但是當且僅當你的 SynchronizationContext 行為異常時,這既適當又必要,並且不代表額外的開銷。

本類庫將特別嘗試檢測 LegacyAspNetSynchronizationContext,但這並不總是可靠的。 該標誌也可用於其他類似情況的手動使用。

原文地址:Thread Theft