WCF AsyncPattern + Task <t> .Factory.FromAsync = ContextSwitchDeadlock </t>

时间:2013-02-14 14:15:34

标签: c# .net wcf task-parallel-library

我正在尝试通过使用Task.Factory.FromAsync将调用包装到客户端上的Task来简化对WCF异步操作的调用。但是当我Start()包装的Task时,对Start()的调用会阻塞客户端,直到调试器报告ContextSwitchDeadlock。但是,可以正确调用服务器端操作。我错过了什么?

WCF合同:

[ServiceContract(Namespace = "urn:test/test")]
public interface ITestContract
{
    [OperationContract(AsyncPattern=true)]
    IAsyncResult BeginGetResult(AsyncCallback callback, object state);

    int EndGetResult(IAsyncResult result);
}

客户代码:

var task = Task<int>.Factory.FromAsync(
    (callback, state) => service.BeginGetResult(callback, state),
    (result) => service.EndGetResult(result)
);
task.Start(); // blocks until ContextSwitchDeadlock gets reported
编辑:只是为了完整性:不,我不能使用.NET 4.5异步/等待模式,因为.NET 4.0(即Windows XP和Server 2003支持)是我项目的一项硬性要求。

EDIT2:

无论如何都不需要调用Start()。真正的问题是,在我调用BeginGetResultStart()Wait()之前,Result不会在服务器端调用 - 这与同步调用相同。

正如我发现的那样,这与任务完全无关。如果我执行以下操作,我会得到相同的结果:

var asyncResult = service.BeginGetResult(null, null); // BeginGetResult NOT invoked on server side!
asyncResult.AsyncWaitHandle.WaitOne(); // Now BeginGetResult actually gets invoked

EDIT3:

事实证明,这对我来说只是一个误解。我希望在客户端调用BeginGetResult 立即调用服务器端的相应BeginGetResult,即客户端的BeginGetResult将阻塞,直到服务器实际上获得了一个请求,但似乎并非如此。显然,请求是在后台线程中发送的,因此客户端和服务器端调用BeginGetResult之间可能会有延迟。我认为这种行为是可以预期的,所以一切都很好: - )。

1 个答案:

答案 0 :(得分:3)

您无需在Start创建的Task上致电FromAsyncStart仅适用于包含代码的任务,FromAsync任务没有任何代码。