WCF ServiceContract的方法返回Task <t>和timeout </t>

时间:2013-07-25 09:46:10

标签: wcf

我是WCF的新手。我正在制作一项服务,我需要在其中计算冗长的操作。 由于该方法很长,我以为我可以通过返回一个Task来使操作异步。 但它不起作用。我还在收到Timeout异常。 示例代码(不是我的实际代码)在下面演示我的问题:

[ServiceContract]
public interface ICalculator
{
   [OperationContract] 
   Task<double> ComputePiAsync(ulong numDecimals);
}

internal class Calculator : ICalculator
{
    public async Task<double> ComputePiAsync(ulong numDecimals)
    {
        return await SomeVeryVeryLongWayOfComputingPi(numDecimals);
    }
}

// server
using (var host = new ServiceHost(typeof(Calculator), new Uri("net.pipe://localhost")))
{
    host.AddServiceEndpoint(typeof(ICalculator), new NetNamedPipeBinding(), "Calculator");
    host.Open();

    Console.WriteLine("Service is running. Press <ENTER> to exit.");
    Console.ReadLine();

    host.Close();
}

// client
var factory = new ChannelFactory<ICalculator>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/Calculator"));
var calculator = factory.CreateChannel();
await calculator.ComputePiAsync(numDecimals); // <--- this call takes longer than 1 minute and I'm getting a timeout here.

那么我应该怎样做才能在我的服务上调用冗长的操作并异步等待结果呢? 增加超时? 如果我增加操作超时,那么让该方法返回任务是什么意思?

2 个答案:

答案 0 :(得分:15)

  

由于该方法很长,我以为我可以使操作异步

按住,放慢速度 - 您正在将异步网络操作超时混合在一起。

首先考虑异步

<强> 1。使用async/await 异步从客户端调用WCF服务

客户端的

async/await帮助我们编写异步程序,以便应用程序保持响应 - 如果说WPF/WinForm我们不希望通过同步调用WCF服务来冻结UI UI线程。相反,我们可以使用async/await将其称为异步。这里的神奇之处在于,这是完整的客户端功能 - 意味着服务不需要是异步的,或者不需要返回Task - 您在创建service reference(proxy)时必须要做的就是告诉Visual Studio 1}}生成基于Task的异步操作 - 然后您可以在客户端上使用async/await

<强> 2。那么async/await在服务方面需要什么?

服务本身可以执行某些I/O之类的查询某些数据源,或者转而调用其他服务。通过在服务端使用async/await - 服务可以异步执行这些操作 - 而不会阻止任何服务线程。这意味着服务有更多的免费线程来为新客户服务 - 因此服务规模要好得多。

现在,上面两个不应该与长时间运行服务操作相混淆

当您的服务需要很长时间才能获得结果时,您正在处理网络超时。您不能也不应该尝试在没有任何活动的情况下无限期地保持网络连接。 WCF通过配置各种超时来帮助您解决此问题。如果您的服务方法需要很长时间才能响应,则必须增加这些超时。如果要将进度报告回客户端,可以考虑使用WCF callback contracts。如果这不足以满足您的要求,那么重新设计您的服务,以便客户端可以启动长时间运行的进程,然后调用服务上的另一个方法来查询状态。

答案 1 :(得分:0)

首先,您必须确保问题确实是异步调用。尝试同步调用您的服务以查看调用是否成功。

假设您的问题实际上是异步操作,您应该使用WCF IAsyncResult而不是async,因为这是在WCF中处理异步操作的默认方式。您将需要一个操作来开始服务,另一个操作来处​​理结果。

我可以编写一些代码,但这里有一些很好的帖子可以解释我的观点,值得一读:

  

另一个提示:

     

执行这些步骤后,如果您意识到客户端需要更多时间来处理异步   执行时,考虑增加operation timeout以允许更长的等待返回。如果   连接不稳定,请考虑将open timeout增加到   给客户更多时间建立联系。

希望它有所帮助。