5

我有一个针对 Profile158(Windows Store、.NET 4.5、Silverlight 5、Windows Phone 8)的可移植类库 (PCL)。我可以轻松地使用返回一种任务类型的方法,并且一切都按我的预期工作。每当我访问 Result 属性时,它都会完成异步代码的运行并返回结果。

但是,如果我在 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();
}

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

string html = request.Test().Result;

它永远不会回来......

4

1 回答 1

3

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

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

因此,您正在async从 UI 线程(提供SynchronizationContext)调用方法,然后通过调用Result. 该async方法无法完成,因为它试图在被阻塞的 UI 线程上完成。

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

  1. 一直使用async下去。不要在方法返回的 s上调用Result或;改为使用。WaitTaskasyncawait
  2. ConfigureAwait(false)尽可能在您的库代码中使用。

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

于 2013-01-31T17:46:03.317 回答