2013-01-31 42 views
5

我有一個針對Profile158(Windows應用商店,.NET 4.5,Silverlight 5,Windows Phone 8)的可移植類庫(PCL)。我可以輕鬆地處理返回任務類型的方法,並且它可以像我期望的那樣工作。無論何時訪問Result屬性,它都會結束運行異步代碼並返回結果。在Mono Droid中使用PCL中的Microsoft.bcl.async?

但是,如果我在PCL中的方法中使用async/await關鍵字,我會返回一個任務。但是,當我嘗試訪問Result屬性時,它會阻止並永遠不會返回。

望着在這兩種情況下我看到了相同的文本在Visual Studio調試輸出窗口:

Thread started: 
Thread started: 
Loaded assembly: Mono.Security.dll [External] 
Thread started: 
Thread started: 

所以它看起來好像代碼正在運行,但它永遠不會返回到UI線程。是否有其他人試圖在PCL中使用Microsoft.bcl.async中的PCL?

我的Mono Droid項目針對Android 2.1。

感謝, 約翰 -

更新:
下面是關於不同情景的一些附加信息。首先,這裏是代碼,它寫在UI代碼時在Mono Droid的工作:

var task = request.GetResponseAsync(); 
string html = task.Result.GetResponseText(); 

然後我創造了PCL下面的方法:

public async Task<string> Test() 
{ 
    IHttpResponse responce = await GetResponseAsync(); 
    return responce.GetResponseText(); 
} 

,並使用從該代碼調用它單UI代碼:

string html = request.Test().Result; 

它永遠不會返回......

+0

如果使用Result屬性,則該屬性將阻塞,直到任務完成。如果你從任務本身需要執行的同一線程那樣做,你基本上給自己一個僵局。目前還不清楚你的代碼是做什麼的......你有一個簡短而完整的程序來證明這個問題嗎? –

+0

@dsplaisted在BUILD的演示期間使用了MonoDroid的這一層 - http://channel9.msdn.com/Events/Build/2012/3-004 - 我將PCL標籤添加到這篇文章中,併發出一個bat信號 - 他會在雷德蒙德時間內...... – Stuart

+0

與您的問題無關,但Microsoft.Bcl.Async仍處於測試階段。應該避免在任何生產代碼中使用它。當然,你現在可能只是在測試它。 –

回答

3

這是一個classic deadlock scenario,一我在我的博客上描述。

默認情況下,await將捕獲「上下文」並使用它來恢復方法。此「上下文」是當前的SynchronizationContext,除非它是null,在這種情況下,它是當前的TaskScheduler

因此,您從UI線程(它提供SynchronizationContext)調用async方法,然後通過調用Result來阻塞UI線程。 async方法無法完成,因爲它試圖在被阻止的UI線程上完成。

爲了解決這個問題,請遵循以下原則:

  1. 使用async一路下跌。不要致電ResultWaitTaskasync返回的方法;改爲使用await
  2. 儘可能在您的庫代碼中使用ConfigureAwait(false)

您可能還會發現我的async/await intro有幫助。

+0

我很好,直到操作完成才能阻止UI代碼。問題是它永遠不會結束,永遠不會返回到UI線程。如果我從我的方法返回一個任務,並且不使用async/await,則UI代碼將暫時封鎖,然後返回。 我已經嘗試了與Windows Phone 8和Windows Store應用程序相同的確切UI代碼,並且它們都正確返回到UI線程。我也檢查過,以確保SynchronizationContext在Android中不爲null,而不是。所以有一些關於Android和PCL的使用異步/等待似乎導致了這個問題。 –

+0

所有UI中都存在相同的死鎖,包括WP8和netcore。如果您的代碼在WP8中的'async'方法中使用'Result',而沒有發生死鎖,並且Android中存在相同的* exact *代碼死鎖,那麼請發佈代碼。 –

+0

我剛剛發佈了代碼。 –