WCF AsyncPattern+任务<;T>;.工厂FromAsync=上下文切换死锁

本文关键字:FromAsync 死锁 工厂 上下文切换 AsyncPattern+ 任务 lt WCF gt | 更新日期: 2023-09-27 17:59:23

我正试图通过使用Task将对WCF异步操作的调用封装到客户端的Task中来简化对该操作的调用。工厂FromAsync。但是,当我启动()包装的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支持)是我项目的一个硬性要求。

第2版:

无论如何,对Start()的调用都不应该是必需的。真正的问题是,直到我调用Start()Wait()ResultBeginGetResult才会在服务器端被调用——这相当于同步调用。

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

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

第3版:

事实证明,这一切只是我的一个误解。我预计在客户端调用BeginGetResult会立即调用服务器端相应的BeginGetResult,即客户端的BeginGetResult会阻塞,直到服务器真正收到请求,但事实并非如此。显然,请求是在后台线程中发送的,因此客户端和服务器端对BeginGetResult的调用之间可能存在延迟。我想这种行为是意料之中的,所以一切都很好:-)。

WCF AsyncPattern+任务<;T>;.工厂FromAsync=上下文切换死锁

您不需要在FromAsync创建的Task上调用StartStart只适用于有代码的任务,而FromAsync任务没有任何代码。