1

我在使用应用程序中的单个 Wcf 服务时遇到问题。它里面有大约 150 个 [OperationContract]。我现在不能再在 Visual Studio 2008 中更新服务参考。

当我尝试调用更新时,我收到各种奇怪的错误,从“套接字强制关闭”到“无效类型”和其他奇怪的消息。如果我注释掉 10-20 个操作,它工作正常。

我在这里、MSDN 和许多博客上阅读了各种帖子。它们都指向需要更改的绑定配置,无论是在主绑定上还是在 MetadataExchange 绑定上。

我的问题是我已经尝试了所有这些,但还没有让它可靠地工作。

我在应用程序中自行托管服务,并且同一个应用程序也是客户端。它们共享相同的配置文件(当前),因为我们正在通过 Wcf 服务层将应用程序分成两部分。

以下是我定义的绑定的摘录:

<system.serviceModel>

    <bindings>
      <netTcpBinding>
        <binding name="NetTcpBinding_IRhinoServices"
                 closeTimeout="00:05:00"
                 openTimeout="00:05:00"
                 receiveTimeout="00:15:00"
                 sendTimeout="00:05:00"
                 transactionFlow="false"
                 transferMode="Buffered"
                 transactionProtocol="OleTransactions"
                 hostNameComparisonMode="StrongWildcard"
                 listenBacklog="100"
                 maxBufferPoolSize="2147483647"
                 maxBufferSize="2147483647"
                 maxConnections="100"
                 maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="2147483647"
                        maxStringContentLength="2147483647"
                        maxArrayLength="2147483647"
                        maxBytesPerRead="2147483647"
                        maxNameTableCharCount="2147483647" />
          <reliableSession ordered="true"
                           inactivityTimeout="00:10:00"
                           enabled="false" />
          <security mode="None">
          </security>
        </binding>
      </netTcpBinding>

      <customBinding>
        <binding name="customMex">
          <textMessageEncoding>
            <readerQuotas maxDepth="2147483647"
                          maxStringContentLength="2147483647"
                          maxArrayLength="2147483647"
                          maxBytesPerRead="2147483647"
                          maxNameTableCharCount="2147483647" />
          </textMessageEncoding>
          <tcpTransport transferMode="Buffered"
                        maxReceivedMessageSize="2147483647"
                        maxBufferSize="2147483647"/>
        </binding>
      </customBinding>

    </bindings>

    <client>
      <endpoint address="net.tcp://localhost:8523/RhinoServices"
                binding="netTcpBinding"
                bindingConfiguration="NetTcpBinding_IRhinoServices"
                contract="RhinoServicesReference.IRhinoServices"
                name="NetTcpBinding_IRhinoServices">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
    </client>

    <services>
      <service behaviorConfiguration="CounterSketchServer.RhinoServicesBehavior"
               name="CounterSketchServer.RhinoServices">
        <endpoint address=""
                  binding="netTcpBinding"
                  contract="CounterSketchServer.IRhinoServices">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>

        <endpoint address="mex"
                  binding="customBinding"
                  contract="IMetadataExchange"
                  name=""
                  bindingConfiguration="customMex"
                  listenUriMode="Explicit" />

        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:8523/RhinoServices" />
          </baseAddresses>
        </host>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="CounterSketchServer.RhinoServicesBehavior">
          <serviceMetadata httpGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>

我需要能够通过单击更新服务参考来生成代理类,这在过去两周内运行良好,直到我达到了这个神秘的限制。

我见过的大多数解决这个问题的例子都是关于 mex 的 http 绑定,但如果可能的话,我想坚持使用 netTcp,因为我是自托管的。

谁能帮帮我吗?

谢谢你。

* 更新 *

我已经尝试过@Aliostad 的建议,起初它似乎运作良好。直到我尝试了一些更新 UI 元素的 Wcf 调用。在将 NetTCP 绑定与 Visual Studios(添加服务引用)工具生成的代理类一起使用时,这些碰巧起作用。但是当使用 Channel Factory 时它不起作用。

我曾尝试查看 Juval 的 WCF 书中的 SyncrhonizationContext,但我所做的一切似乎都不起作用。

我尝试使用命名管道和 NetTCP 作为我使用 ChannelFactory 创建的 Channel 的绑定,它们的行为似乎与长时间运行的 Wcf 操作有很大不同,但两者都不能更新 UI 元素。

我的服务实际上是在 Rhino 3D CAD 引擎的插件中运行的,并且 Ceratin 调用(渲染等)会触发 Rhino 中的 UI 进行更新。我认为这会导致线程边界问题。我收到的异常是: 试图读取或写入受保护的内存

如果有人对在这种情况下有效使用 ChannelFactory 方法或解决给定 Wcf 类中操作过多以生成服务代理的问题有任何建议,我将不胜感激。

谢谢你!

4

2 回答 2

2

首先,我认为唯一的解决方案是删除引用,然后重新添加。


或者,如果您同时拥有客户端和服务——我似乎是从阅读你的问题中得到的——我是否强烈建议您与客户共享服务接口——而不是使用服务参考?

当您同时拥有客户端和服务器时,这绝对是首选方法(并将使您免于遇到的所有麻烦),我相信如果您不拥有客户端,这也是首选方法,您只需共享实体/dtos 和接口。

这要求您:

  • 为您的实体/dtos 创建一个类库项目。与客户分享。
  • 为您的服务接口创建一个类库项目。与客户分享。
  • 为您的服务实现创建一个类库项目。只停留在服务器上。
  • 客户端使用ChannelFactory<T>创建工厂,然后通过调用创建代理CreateChannel()
于 2011-04-13T22:00:58.107 回答
1

我已经从 SvcUtil.exe 和 Visual Studio 2008 中重新获得了更新服务参考。

为此,我在devenv.exe.configSvcUtil.exe.config的配置文件中添加了以下部分:

<!-- CUSTOM MetaDataExchaning Binding to all for LARGE WCF Services -->

<client>
    <endpoint name="net.tcp" binding="netTcpBinding" bindingConfiguration="GenericBinding"
    contract="IMetadataExchange" />
    <endpoint name="http" binding="wsHttpBinding" bindingConfiguration="SecureBinding" contract="IMetadataExchange" />
</client>

<bindings>

    <netTcpBinding>
        <binding name="GenericBinding" maxBufferPoolSize="2147483647"
        maxReceivedMessageSize="2147483647" >
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
            maxArrayLength="2147483647" maxBytesPerRead="2147483647"
            maxNameTableCharCount="2147483647" />
            <security mode="None"/>
        </binding>
    </netTcpBinding>

    <wsHttpBinding>
        <binding name="SecureBinding" maxBufferPoolSize="2147483647"
        maxReceivedMessageSize="2147483647" >
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
            maxArrayLength="2147483647" maxBytesPerRead="2147483647"
            maxNameTableCharCount="2147483647" />
            <security mode="Message">
                <transport clientCredentialType="Windows" />
            </security>
        </binding>
    </wsHttpBinding>
</bindings>

然后在我的应用程序服务器插件中,我仍然以编程方式创建ServiceHost,以便启用元数据交换,我添加了另一个端点:

        // DATA ENDPOINT
        NetTcpBinding binding = new NetTcpBinding(SecurityMode.Transport, true);
        Uri baseAddress = new Uri("net.tcp://localhost:8555/RhinoServices");
        _rhinoServicesHost = new ServiceHost(typeof(RhinoServices), baseAddress);
        _rhinoServicesHost.AddServiceEndpoint(typeof(IRhinoServices), binding, baseAddress);

        // META ENDPOINT
        BindingElement bindingElement = new TcpTransportBindingElement();
        CustomBinding customBinding = new CustomBinding(bindingElement);
        ServiceMetadataBehavior metadataBehavior = _rhinoServicesHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
        if (metadataBehavior == null)
        {
            metadataBehavior = new ServiceMetadataBehavior();
            _rhinoServicesHost.Description.Behaviors.Add(metadataBehavior);
        }
        _rhinoServicesHost.AddServiceEndpoint(typeof(IMetadataExchange), customBinding, "MEX");

        _rhinoServicesHost.Faulted += RhinoServicesHost_Faulted;
        _rhinoServicesHost.Open();

无论合同数量如何,我现在都可以更新参考。

不过我不得不承认,在整个过程中,出现的尝试读取或写入受保护的内存错误并没有消失,因为我切换回了这种方法。

所以我想我仍然必须追踪它......

我还在另一个问题上找到了这个解决方案(点击查看),由@trendl 回答。谢谢您的帮助。

于 2011-04-15T17:31:13.303 回答