未调用WCF服务回调

时间:2013-09-30 11:21:22

标签: c# wcf

我在WCF服务中使用tcp绑定,而在客户端的回调没有被调用。这是我的代码

服务

 public interface IMyContractCallback
{
   [OperationContract(IsOneWay = true)]  
    void OnCallback();
}

[ServiceContract(CallbackContract = typeof (IMyContractCallback),SessionMode =
 SessionMode.Required)]
public interface IService1
{

     [OperationContract(IsOneWay = true)]  
    void DoSomething();      


      [OperationContract]
    int GetCount();
}

 public class Service1 : IService1
{

    private int count=0;   
    public int GetCount()
    {
        return count;
    }

    public void DoSomething()
    {
        count++;
        Console.WriteLine("increased count");
       IMyContractCallback callback =  
                 OperationContext.Current.GetCallbackChannel<IMyContractCallback>();

            if ((callback as IChannel).State == CommunicationState.Opened)
            {
                callback.OnCallback();
            }

    }       
}

我的客户是

public class App1
{


    private MyServiceCallback callback;
    private InstanceContext context;
    private Service1Client proxy;       

    public App1()
    {
        callback=new MyServiceCallback();


        context = new InstanceContext(callback);
        var factory = new DuplexChannelFactory<IService1>(callback, "EndPointTCP");
        IService1 proxy = factory.CreateChannel();

        callback.proxy = proxy;

        proxy.DoSomething();


    }
}

public class MyServiceCallback : IService1Callback
{

    public IService1 proxy
    {
        get;
        set;
    }
    public void OnCallback()
    {

        Console.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
        Console.WriteLine(proxy.GetCount());

    }
}

我面临两个问题:

1.我没有收到上述代码的DoSomething回调。 2.如果我将DoSomething声明为Twoway,我会收到回调,但它会抛出异常“服务器未提供有意义的回复”

我的客户端配置

<?xml version="1.0" encoding="utf-8" ?>
  <configuration>
<system.serviceModel>
    <bindings>
        <netTcpBinding>
            <binding name="EndPointTCP" closeTimeout="00:10:00" openTimeout="00:10:00"
                receiveTimeout="00:10:00" sendTimeout="00:10:00"
                transactionFlow="false"
                transferMode="Buffered" transactionProtocol="OleTransactions"
                hostNameComparisonMode="StrongWildcard" listenBacklog="10"
                maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
                maxReceivedMessageSize="65536">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" 
                 maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <reliableSession ordered="true" inactivityTimeout="00:20:00"
                    enabled="true" />
                <security mode="Transport">
                    <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
                    <message clientCredentialType="Windows" />
                </security>
            </binding>
        </netTcpBinding>
        <wsDualHttpBinding>
            <binding name="EndPointHTTP" closeTimeout="00:01:00" openTimeout="00:01:00"
                receiveTimeout="00:10:00" sendTimeout="00:01:00" 
                bypassProxyOnLocal="false"
                transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" 
                   maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00" />
                <security mode="Message">
                    <message clientCredentialType="Windows" 
                           negotiateServiceCredential="true"
                        algorithmSuite="Default" />
                </security>
            </binding>
        </wsDualHttpBinding>
    </bindings>
    <client>
        <endpoint address="masked"
            binding="wsDualHttpBinding" bindingConfiguration="EndPointHTTP"
            contract="ServiceReference1.IService1" name="EndPointHTTP">
            <identity>
                <servicePrincipalName value="masked" />
            </identity>
        </endpoint>
        <endpoint address="masked"
            binding="netTcpBinding" bindingConfiguration="EndPointTCP"
            contract="ServiceReference1.IService1" name="EndPointTCP">
            <identity>
                <servicePrincipalName value="masked" />
            </identity>
        </endpoint>
    </client>
</system.serviceModel>
  </configuration>

我的服务配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration>


<system.web>
<compilation debug="true" targetFramework="4.0"/>
<httpRuntime maxRequestLength="102400" />

 </system.web>

<system.diagnostics>
 <sources>
  <source name="System.ServiceModel"
          switchValue="Information, ActivityTracing"
          propagateActivity="true">
    <listeners>
      <add name="traceListener"
          type="System.Diagnostics.XmlWriterTraceListener"
          initializeData= "d:\log\Traces.svclog" />
    </listeners>
  </source>
 </sources>
 </system.diagnostics>

 <system.serviceModel>
<bindings>
  <netTcpBinding>
    <binding name="TcpBinding" maxBufferPoolSize="2147483647"  
       maxBufferSize="2147483647"
      maxReceivedMessageSize="2147483647" portSharingEnabled="true" >
      <readerQuotas maxDepth="32" maxStringContentLength="2147483647" 
        maxArrayLength="2147483647"
        maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
      <security mode="Transport"/>
      <reliableSession enabled="true" />
    </binding>
  </netTcpBinding>
</bindings>
<services>
  <service behaviorConfiguration="WcfService2.MyServiceBehaviour" 
   name="WcfService2.Service1">
    <endpoint address="" binding="wsDualHttpBinding" bindingConfiguration=""
      name="EndPointHTTP" contract="WcfService2.IService1" />
    <endpoint address="" binding="netTcpBinding" bindingConfiguration="TcpBinding"
      name="EndPointTCP" contract="WcfService2.IService1" isSystemEndpoint="false" />
    <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""
      name="mexpoint" contract="IMetadataExchange" />
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="WcfService2.MyServiceBehaviour">
      <serviceMetadata httpGetEnabled="false"  />
      <serviceThrottling maxConcurrentSessions="10000"/>
      <serviceDebug includeExceptionDetailInFaults="true" />
      <dataContractSerializer maxItemsInObjectGraph="2147483647" />
    </behavior>
  </serviceBehaviors>
   </behaviors>
 </system.serviceModel>
 <system.webServer>
  <modules runAllManagedModulesForAllRequests="true" />
  <directoryBrowse enabled="true" showFlags="Date, Time, Size, Extension, LongDate" />
  </system.webServer>

  </configuration>

2 个答案:

答案 0 :(得分:3)

问题是,您正在从回调中再次调用该服务。如果你不这样做,那就没有关于“没有意义的答案”的错误。

将ConcurrencyMode属性设置为您的服务和回调类应该会有所帮助:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service1 : IService1
...

[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MyServiceCallback : IService1Callback
...

当然,你必须在OperationContract中设置“IsOneWay = false”。

答案 1 :(得分:1)

它应该可以使用IsOneWay = true ..

这是一个例子

----服务代码

[ServiceContract(CallbackContract = typeof(IServerFinishedProcessingCallback), SessionMode = SessionMode.Required)]
public interface IDualMathService
{
    [OperationContract(IsOneWay=true)]
    void ProcessAdd(double num1, double num2);

    [OperationContract(IsOneWay = true)]
    void ProcessSubtract(double num1, double num2);

    [OperationContract(IsOneWay=true)]
    void ProcessMultiply(double num1, double num2);

    [OperationContract(IsOneWay=true)]
    void ProcessDivide(double num1, double num2);
}            
public interface IServerFinishedProcessingCallback
{        
    [OperationContract(IsOneWay=true)]
    void ProcessingFinished(string operation, double result);
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class DualMathServiceClass : IDualMathService
{
    readonly IServerFinishedProcessingCallback _clientCode = OperationContext.Current.GetCallbackChannel<IServerFinishedProcessingCallback>();
    //[PrincipalPermission()]
    public void ProcessAdd(double num1, double num2)
    {
        Console.WriteLine("Processing Request for client session ID " + OperationContext.Current.SessionId);
        Console.WriteLine(string.Format("Processing Add Request for parameters {0} and {1} ", num1, num2));
        _clientCode.ProcessingFinished("Add", (num1 + num2));
    }
    public void ProcessSubtract(double num1, double num2)
    {
        Console.WriteLine("Processing Request for client session ID " + OperationContext.Current.SessionId);
        Console.WriteLine(string.Format("Processing Subtract Request for parameters {0} and {1} ", num1, num2));
        _clientCode.ProcessingFinished("Subtract", (num1 - num2));
    }
    public void ProcessMultiply(double num1, double num2)
    {
        Console.WriteLine("Processing Request for client session ID " + OperationContext.Current.SessionId);
        Console.WriteLine(string.Format("Processing Multiply Request for parameters {0} and {1} ", num1, num2));
        _clientCode.ProcessingFinished("Multiply", (num1 * num2));
    }
    public void ProcessDivide(double num1, double num2)
    {
        Console.WriteLine("Processing Request for client session ID " + OperationContext.Current.SessionId);
        Console.WriteLine(string.Format("Processing Divide Request for parameters {0} and {1} ", num1, num2));
        if (num2 == 0)
            throw new FaultException<string>("Number 2 can not be zer");
        _clientCode.ProcessingFinished("Divide", (num1 / num2));
    }
}

客户代码

[CallbackBehavior(IncludeExceptionDetailInFaults = true,
    UseSynchronizationContext = true,
    ValidateMustUnderstand =true,
    ConcurrencyMode = ConcurrencyMode.Multiple)]
public class ClientCallbackClass : IDualMathServiceCallback
{
    public delegate void ProceFinishedEventDelegate(string operation, double result);
    public event ProceFinishedEventDelegate ProcessFinishedEvent = null;
    public void ProcessingFinished(string operation, double result)
    {            
        if (ProcessFinishedEvent != null)
        {
            ProcessFinishedEvent(operation, result);
        }
    }
}