8

我是 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.

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

4

2 回答 2

16

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

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

让我们首先考虑异步

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

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

2. 那么async/await服务端需要什么?

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

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

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

于 2013-07-25T10:53:17.753 回答
0

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

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

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

另一个提示:

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

希望能帮助到你。

于 2013-07-25T10:54:27.710 回答