2014-04-18 51 views
4

我添加了一个WCF服务引用到我的.NET 4.5应用程序,使用默认的“生成基于任务的操作”选项下的“允许生成异步操作“。我从我自己的异步方法调用服务,有点像这样:使用.NET 4.5基于任务的异步操作的WCF服务客户端,等待永远不会返回

public async Task<SomeData> GetDataAsync() 
{ 
    var client = new MyServiceClient(); 
    var result = await client.GetSomeDataAsync(); 

    return result; 
} 

await client.GetSomeDataAsync()永远不会完成(在return语句断点从未被击中),我没有得到一个超时或任何其他错误,不会引发异常,什么都不是。 Fiddler显示客户端发送了请求,服务几乎立即响应了预期的数据,所以问题出现在围栏的一边。

如果我切换到同步版本而不是

var result = client.GetSomeData(); 

调用返回预期。

我在做什么错?

+0

你怎么知道你的等待声明永远不会完成?在你的例子中,你只是返回结果。您可以尝试在await语句之后放置语句,以尝试访问result.Result属性以查看是否存在任何内容。 – jensendp

+0

return语句永远不会被执行。我设置了一个断点并试图通过等待,它从未继续。 –

+0

你的调用代码刚开始执行任务,你没有显示你如何观察其结果。这很重要。 – Servy

回答

20

chest hairs are tingling,T先生我强烈怀疑,进一步您(客户端)调用堆栈,你有一些代码,呼吁Task<T>.ResultTask.Wait,这significantly increases the possibility of a deadlock(我在我的博客解释)。

默认情况下,当你await一个Task,在await将捕获“上下文”,并用它来恢复async方法。如果这是一个类似于UI线程上下文的上下文,并且然后代码阻止了 UI线程(即,调用ResultWait),则该方法不能在该UI线程上恢复。

I pity the fool谁试图混合同步和异步代码。只需使用async all the way(正如我在MSDN文章中所描述的那样)。

+2

几乎不得不为你所有的T先生参考文献付出代价。 ;-) – jensendp

+0

你的Spidey Sense已经死了!在我的“上游”代码中,我当然在做'GetDataAsync()。Result' - 我调用'.Result'的方法是基类方法的非异步覆盖,我不知道如何解决这个限制。我会检查你的答案中的链接,并以正确的方式做到这一点... –

+0

是的,我完全错过了T先生的参考... ;-) –