我是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.
那么我应该怎样做才能在我的服务上调用冗长的操作并异步等待结果呢? 增加超时? 如果我增加操作超时,那么让该方法返回任务是什么意思?
答案 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中处理异步操作的默认方式。您将需要一个操作来开始服务,另一个操作来处理结果。
我可以编写一些代码,但这里有一些很好的帖子可以解释我的观点,值得一读:
async
字出现在WCF服务之前,并且使用Task来保持WCF调用内的操作。如果您有多个操作,它可能很有用异步调用服务器)另一个提示:
执行这些步骤后,如果您意识到客户端需要更多时间来处理异步 执行时,考虑增加
operation timeout
以允许更长的等待返回。如果 连接不稳定,请考虑将open timeout
增加到 给客户更多时间建立联系。
希望它有所帮助。