簡體   English   中英

在PCL和Windows Phone應用程序中實現異步作用域

[英]Implementing asynchronous scoping in PCL and Windows Phone applications

出於某種奇怪的原因,只有使用完整的CLR才能使用System.Runtime.Remoting.Messaging.CallContextAsyncLocal類。 這使得在使用可移植類庫或Windows Phone應用程序時進行異步作用非常困難,特別是因為Windows Phone API變得異步; 所以我們沒有選擇不使用async / await。

這實際意味着在WPF或WinForms中,我們可以編寫這樣的方法:

private async void button_Click(object sender, EventArgs e)
{
    CallContext.LogicalSetData("x", new object());
    await Something();
    var context = CallContext.LogicalGetData("x");
}

在WPF和WinForms中,框架確保每次單擊到同一個按鈕都可以獲得自己的上下文,並且可以單獨運行。 使用ThreadLocal<T>[ThreadStatic]很難實現相同的功能,因為每次點擊都會在UI線程上執行。

我的問題是,我們如何在Windows Phone,Store和其他不支持CallContextAsyncLocal<T>應用程序類型中解決此問題?

一些背景資料:

我們經常希望(業務)邏輯在某種上下文中運行。 此上下文可以包含業務邏輯可以在整個操作中使用的信息。 在服務器環境中,這很容易想象,因為您需要在數據庫事務中運行請求,需要訪問當前用戶,租戶ID等。但即使在客戶端應用程序中,操作也可能需要訪問上下文信息,例如用於記錄的當前運行操作或上下文的相關ID。 在此類操作期間(如點擊事件),我們可能需要解析其他服務(來自我們的合成根 )。 為了使操作成功,我們可能需要在整個客戶端操作中重用相同的組件,這意味着我們的組合根需要知道它正在運行的上下文。

雖然所有這些信息都可以使用服務公共API的方法調用在整個系統中傳遞,但這不僅會迫使我們使用實現細節污染應用程序中的服務的API,而且會導致嚴重的維護問題,因為我們必須在整個系統中傳遞所有這些信息,並且對我們的一個組件的簡單內部更改將通過所有方法調用向上傳播調用堆棧。 當涉及到我們的Composition Root時,我們絕對不希望通過應用程序傳遞我們的DI庫的一些緩存/范圍對象,因為這會將我們的業務邏輯緊密地耦合到外部庫。 顯然,我們也不想傳遞某種服務定位器

因此,在客戶端應用程序中使用CallContextAsyncLocal<T>等實現范圍界定非常重要。

對不起,今天沒有簡單的解決方案。 當Windows Phone(最終)成為“手機上的Windows 10”(即使用AsyncLocal<T> )時,這將是可能的。 但現在...

做到這一點的最簡單的方法是通過上下文中,明確地(作為一個參數)或隱含地(如在一個成員變量this )。

也可以通過自定義等待者來實現這種限制版本。 但除了非常復雜之外,該解決方案還需要您修改整個應用程序中的每個await (或使用后編譯IL重寫來實現相同的效果)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM