【问题标题】:WCF ServiceContract's method returning Task<T> and timeoutWCF ServiceContract 的方法返回 Task<T> 和超时
【发布时间】:2013-07-25 09:46:10
【问题描述】:

我是 WCF 的新手。我正在提供一项需要计算冗长操作的服务。 由于该方法很长,我想我可以通过返回一个任务来使操作异步。 但它不起作用。我仍然收到超时异常。 示例代码(不是我的实际代码)在下面展示了我的问题:

[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.

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

【问题讨论】:

    标签: wcf


    【解决方案1】:

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

    等等,慢点——你把异步网络操作超时混为一谈了。

    让我们首先考虑异步

    1.使用async/await异步从客户端调用 WCF 服务

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

    2。那么服务端async/await有什么需求呢?

    服务本身可能会执行一些I/O,例如查询某些数据源或反过来调用另一个服务。通过在服务端使用async/await - 服务可以异步执行这些操作 - 不会阻塞任何服务线程。这意味着服务有更多的空闲线程来服务新客户——因此服务的扩展性要好得多。

    现在,以上两个不应与长期运行服务操作混淆

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

    【讨论】:

    • +1。说明最后一点,服务器端的async 不会尽快返回给客户端。只有在返回的任务完成后才会向客户端发送响应。
    • @StephenCleary:谢谢。是的,服务端 async/await 异步对客户端不可见。
    • 有价值的问题和良好、清晰的答案。如果调用长时间运行,因为服务上的操作需要大量计算时间,我不确定我是否会引用它,但会导致网络超时。我想这些与发送/接收超时有关,而操作超时与那些+计算时间有关?
    • @TimBarrass:我使用网络超时作为通用术语,而不是任何特定的超时。由于服务器上的计算时间较长以及网络延迟,WCF 客户端操作可能会超时。
    【解决方案2】:

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

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

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

    另一个提示:

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

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-23
      • 2018-10-13
      • 2016-10-05
      • 1970-01-01
      • 2014-08-14
      • 1970-01-01
      • 1970-01-01
      • 2015-01-01
      相关资源
      最近更新 更多