在PCL中使用Mono Droid的Microsoft.bcl.async?

Joh*_*oha 5 xamarin.android portable-class-library

我有一个针对Profile158的便携式类库(PCL)(Windows应用商店,.NET 4.5,Silverlight 5,Windows Phone 8).我可以轻松地使用返回一种Task类型的方法,并且它都可以像我期望的那样工作.每当我访问Result属性时,它就会完成运行异步代码并返回结果.

但是,如果我在PCL中的方法中使用async/await关键字,我会得到一个任务.但是,当我尝试访问Result属性时,它会阻塞并永远不会返回.

在两种情况下查看Visual Studio中的调试输出窗口,我看到相同的文本:

Thread started: 
Thread started: 
Loaded assembly: Mono.Security.dll [External]
Thread started: 
Thread started: 
Run Code Online (Sandbox Code Playgroud)

所以看起来好像代码正在运行,但它永远不会返回到UI线程.有没有其他人试图在PCL中使用带有Microsoft.bcl.async的PCL?

我的Mono Droid项目针对的是Android 2.1.

谢谢, - 约翰

更新:
以下是有关不同方案的一些其他信息.首先,这里是在UI代码中编写时可以在Mono Droid上运行的代码:

var task = request.GetResponseAsync();
string html = task.Result.GetResponseText();
Run Code Online (Sandbox Code Playgroud)

然后我在PCL中创建了以下方法:

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

并使用Mono UI代码中的代码调用它:

string html = request.Test().Result;
Run Code Online (Sandbox Code Playgroud)

它永远不会回归......

Ste*_*ary 3

正如我在博客中所描述的,这是一个典型的死锁场景。

默认情况下,await将捕获“上下文”并使用它来恢复该async方法。这个“上下文”是当前的,SynchronizationContext除非它是null,在这种情况下它是当前的TaskScheduler

因此,您async从 UI 线程(提供SynchronizationContext)调用一个方法,然后通过调用 来阻塞 UI 线程Result。该async方法无法完成,因为它正在尝试在 UI 线程上完成,而该线程已被阻止。

要解决此问题,请遵循以下准则:

  1. async一直往下使用。不要对方法返回的值调用Resultor ;代替使用。WaitTaskasyncawait
  2. ConfigureAwait(false)尽可能在您的库代码中使用。

您可能还会发现我的async/await介绍很有帮助。