2013-04-26 246 views
3

我正在使用Windows 8(使用C#),並且在使用異步關鍵字時,我看起來似乎無法很好地處理異常。捕獲異步lambda異常

該場景涉及啓動async lambda,將其發佈到UI線程上運行。
執行lambda代碼期間發生的異常在調用線程上重新拋出,無法正確捕獲它們。

實施例:這個代碼塊是在某些工作線程執行,並且試圖在UI線程上調度工作:

await Window.Current.Dispatcher.RunAsync 
     (CoreDispatcherPriority.Normal 
     , async() => 
      { 
       var result = await CurrentAppSimulator 
            .RequestProductPurchaseAsync("product, true); 
      } 
     ); 

如果lambda表達式內的代碼拋出異常,該異常是不會轉貼回該方法的正文。相反,它是由SynchronizationContext或類似的機制拋出的,我似乎無法捕捉它。

我想要的是能夠從這段代碼(調用代碼)中捕獲此異常。

這可能嗎?

+0

你爲什麼使用Dispatcher進行呼叫?如果沒有其他線程,則不需要這樣做;異步調用一個函數不會創建一個新線程... – daryal 2013-04-26 08:32:24

+0

另外,您是否在RequestProductPurchaseAsync方法中使用TaskCompletionSource ? – daryal 2013-04-26 08:33:43

+0

此代碼在工作線程上執行。添加到問題中。此外,我不使用TCS 2013-04-26 08:43:17

回答

2

我認爲如果可能的話,你不應該這樣做。 UI線程應該是管理後臺線程中發生的事情的線程,而不是其他方式。

如果你真的需要這一點,你可以使用Task.Factory.StartNew()過載,它可以讓你指定一個TaskScheduler,與Unwrap()一起所產生的Task<Task>變成一個簡單的Task

await Task.Factory.StartNew(
    async() => 
     await CurrentAppSimulator.RequestProductPurchaseAsync("product", true), 
    CancellationToken.None, TaskCreationOptions.None, scheduler) 
    .Unwrap(); 

或者,你可以使用await await

await await Task.Factory.StartNew(
    async() => 
     await CurrentAppSimulator.RequestProductPurchaseAsync("product", true), 
    CancellationToken.None, TaskCreationOptions.None, scheduler); 

這意味着你需要通過UI TaskScheduler(您可以通過撥打得到,而你在UI線程上)到這個方法。

+0

在某些情況下,代碼執行的「位置」不取決於您。在這種情況下,我必須發佈一些代碼到UI線程中... – 2013-04-27 05:25:20