WCF: исключение StackoverFlow - PullRequest
       2

WCF: исключение StackoverFlow

3 голосов
/ 15 декабря 2010

Я получаю исключение при попытке обслуживать класс .NET ServiceController. Он сериализуется нормально, когда он нулевой, но как только я заполняю его, я получаю исключение stackoverflow.

Так что это работает:

    [DataMember]
    public ServiceController MyServiceController
    {
        get { return null; }
    }

Но это выдает ошибку «Произошло необработанное исключение типа« System.StackOverflowException »в System.ServiceProcess.dll»:

public class TestClass
{
    private ServiceController _serviceController;
    [DataMember]
    public ServiceController MyServiceController
    {
        get { return ServiceController.GetServices()[0];
    }
}

Странно, что в логах вообще нет ошибок. Когда есть ошибка, я вижу ее в журналах, так что это не потому, что мои журналы не работают. Вот мой конфигурационный файл

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyCompany.Wcf.RdbmsServer.RdbmsServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="MyCompany.Wcf.RdbmsServer.RdbmsServiceBehavior"
        name="MyCompany.Wcf.RdbmsServer.RdbmsService">
        <endpoint address="" binding="wsHttpBinding" contract="MyCompany.Wcf.RdbmsServer.IRdbmsService" bindingConfiguration="IncreaseMaxMessageSize">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8731/Design_Time_Addresses/MyCompany.Wcf.RdbmsServer/RdbmsService/" />
          </baseAddresses>
        </host>
      </service>
    </services>

    <bindings>
      <wsHttpBinding>
        <binding name="IncreaseMaxMessageSize" 
            maxReceivedMessageSize="655360000">
        </binding>
      </wsHttpBinding>
    </bindings>
  </system.serviceModel>

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="All"
              propagateActivity="true">
        <listeners>
          <add name="traceListener"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData= "c:\Traces.svclog" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

</configuration>

Вот мой сервисный интерфейс

[ServiceContract]
public interface IRdbmsService
{
    [OperationContract]
    TestClass GetServiceControllerList();
}

И реализация:

    public TestClass GetServiceControllerList()
    {
       return new TestClass();
    }

Есть идеи?

Ответы [ 2 ]

3 голосов
/ 15 декабря 2010

Вы вызываете сериализатор для рекурсии:

public class TestClass
{
    private ServiceController _serviceController;
    [DataMember]
    public ServiceController MyServiceController
    {
        get { return ServiceController.GetServices()[0]; // <-- this returns your service
    }
}

Служба, которую вы возвращаете, это IRdbmsService, которая возвращает TestClass. Затем его необходимо сериализовать и т. Д.

Редактировать: Уточнить:

Когда TestClass сериализуется, сериализатор просматривает все его свойства DataMember, одним из которых является ServiceController. Затем он сериализует это свойство, что делает это на get:

return ServiceController.GetServices()[0];

Поскольку IRdbmsService - единственная служба, определенная в вашей области, она находится в индексе 0 в ответе на вызов GetServices, поэтому ее необходимо сериализовать. Поскольку тип возвращаемого значения GetServiceControllerList равен TestClass, необходимо затем сериализовать TestClass, что возвращает нас к началу (отсюда и рекурсия).

Что касается решения этой проблемы, это зависит от того, что вы пытаетесь сделать. В данный момент этот сервис возвращает информацию о себе вызывающей стороне, что для меня не имеет смысла; звонящий уже имеет эту информацию во время потребления (до совершения звонка). Можете ли вы уточнить свои намерения?

0 голосов
/ 15 декабря 2010

Да, в конструкторе ServiceController CLASS вы, вероятно, вызываете что-то рекурсивное, у которого нет условия для остановки, поэтому каждый раз, когда оно вызывает что-то рекурсивное, программа перемещается в стек, и, как я уже сказал, нет условие остановки, оно будет добавлено в стек, пока память не взорвется, поэтому ему присваивается имя ошибки StackOverFlow.

Предложение: добавить точку останова для отладки там, где ее вызов рекурсивен. Это так просто при отладке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...