【问题标题】:Calling multiple operations on a WCF client在 WCF 客户端上调用多个操作
【发布时间】:2012-02-06 11:34:27
【问题描述】:

我目前正在查看一些基本上从文件中逐行读取数据并在 WCF 客户端上为每一行调用适当方法的代码。我的代码问题是为每个操作创建了一个新客户端,即:

function CallSomeOp(line)
 {
   using (var client = new Client()
   {
       client.SomeOp(line);
   }
 }

这似乎使客户端关闭连接并为文件中的每一行重新打开一个新连接,这似乎是一个很大的开销。我想做的是将客户端的创建移到函数之外并进入初始化,以便在一个客户端上调用多个操作,即:

 using (var client = new Client())
 {
     for(var line in lines)
     {
        CallSomeOp(line, client);
     }
 }

但我不确定这是否可行。在客户端上调用多个操作是否有问题,即我最终会耗尽内存还是什么?

【问题讨论】:

    标签: wcf


    【解决方案1】:

    操作通常是无状态的,因此这是预期的行为。您可以更改InstanceContextMode。这决定了每次调用是否都会创建一个新实例,或者是否只有一个实例。问题是,你应该吗?就像我说的,单个调用通常是无状态的。只有一个实例也不能很好地扩展。我建议将InstanceContextMode 保留为 PerCall,这样,对于网络服务器的每次调用都会创建一个实例,我不会太担心开销。如果开销确实成为问题,那么也许服务不是您所需要的。

    然后是ConcurrencyMode,它允许您指定要创建的多个线程。

    就客户端而言,您无需在每次要调用操作时都重新创建它。或者,如果客户端和服务器都知道合同,您也可以查看ChannelFactoryThis answer 提供了一些细节。

    【讨论】:

    • 感谢您的回答,我使用分析器进行了实验,并使用单个实例将运行时间从 58 秒减少到 25 秒左右。我对 WCF 了解不多,但这似乎是快速获胜。
    • 你能发布一些你的服务的代码吗?它有什么作用?请注意,单个实例可能会导致多次调用的扩展问题。
    • 我无法发布服务的代码,我也不完全确定它的作用!它应该只需要一些数据并将其放在某个地方。使用客户端的申请者是单线程的。
    【解决方案2】:

    在多个调用中重用 WCF 客户端绝对是一个好主意,因为 创建它的新实例确实有成本,即使 that's been improved in later versions 也是如此。

    不过,重用 WCF 客户端时要注意的最重要的事情是,如果服务操作失败,整个客户端将被放入 faulted state 并且 可以不再使用

    您必须在客户端代码中考虑到这一点。根据您的要求,处理这种情况的一种方法可能是重新创建客户端代理以防失败并继续处理输入,如下例所示:

    var client = new ServiceClient();
    
    foreach (var line in lines)
    {
        try
        {
            client.DoSomething(line);
        }
        catch
        {
            client.Abort();
            client = new ServiceClient()
        }
    }
    

    请注意,您可能还希望跟踪服务调用失败的次数以及出现何种异常,因为在某些情况下,完全中止操作 而不是继续尝试,例如当远程服务无法访问时。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多