TaskCompletionSource 這個玩意兒是我在 InAppBillingPlugin 這個 GitHub 儲存庫發現的,查了一下 MSDN 它說「代表未與委派繫結之 Task<TResult> 的生產者端,可提供透過 Task 屬性對消費者端的存取。」?????? 它在說什麼?我們來舉個例子。
對 MSDN 所說的我的理解是,如果呼叫端只接受 Task-based 的非同步執行,但是被呼叫端萬一是第三方元件只提供註冊 EventHandler 怎麼辦?這時候被呼叫端就成了 MSDN 所說的「未與委派繫結之 Task<TResult> 的生產者端」,而 InAppBillingPlugin 裡面所要做的事就非常適合 TaskCompletionSource 的使用。
InAppBillingPlugin 是一個 Xamarin.Forms 的 Plugin,方便我們做 iOS 的 In-App Purchases 及 Android 的 In-App Billing,為了不讓 App 的 UI Thread 被卡住,因此我們會經常使用非同步呼叫,而 Task-based 是其中一種方式且非常方便,搭配 async/await
保留字立馬變神器。
iOS 的 In-App Purchases 會使用到他們家的 StoreKit Library,當我們發出購買的要求之後就等 StoreKit 回傳交易結果,我們想要收到回傳的交易結果就必須在 StoreKit 提供的 PaymentQueue 中增加一個 TransactionObserver,而 TransactionObserver 我們又必須實作一個繼承自 SKPaymentTransactionObserver
抽象類別的類別,實例化之後塞進 PaymentQueue。
繼承 SKPaymentTransactionObserver 之後我們還會發現我們要實作 UpdatedTransactions
方法,而 UpdatedTransactions 方法就是當我們送出購買要求之後 StoreKit 會來呼叫並回傳交易結果的地方,我們就在裡面撰寫我們要的處理邏輯,如果我們想要把發出購買要求到接到交易結果的非同步機制轉換成 Task-based 的話,TaskCompletionSource 就登場了。
自訂 Event
我們在我們繼承 SKPaymentTransactionObserver 的類別裡面宣告 event
,並在 UpdatedTransactions 方法裡面找地方 Invoke。
在 EventHandler 內賦予 TaskCompletionSource 結果
TaskCompletionSource 提供了 SetResult()
、SetException()
、SetCanceled()
三個方法來賦予結果
一切準備就緒後,我們在呼叫的時候就可以用 async/await 保留字這個方便的小東西了,雖然實際上是 Event-based 的機制,透過 TaskCompletionSource 我們可以輕鬆地把它轉換成 Task-based 的機制。
< Source Code >