2012-10-23 66 views
0

我有一个WCF服务,我试图让回调工作。回调干扰回拨初始呼叫

所述接口类看起来像:

[ServiceContract(
    SessionMode = SessionMode.Required, 
    CallbackContract = typeof(IPredatorEngineCallback))] 
public interface IMyApplication 
{ 
    [OperationContract] 
    Boolean DoSomething(string mystring); 

    [OperationContract] 
    Boolean SubscribeToEvent(); 

} 

public interface IMyApplicationCallback 
{ 
    [OperationContract (IsOneWay = true)] 
    void EventRaised(EventMessage myEventMessage) 
} 

事件消息是类,这是在由服务器客户机&共享的通讯科库。

该接口的实现是这样的:

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)] 
public class MyApplication : IMyApplication 
{ 
    private List<IMyApplicationCallback> CallbackList = new List<IMyApplicationCallback>; 

    public Boolean DoSomething(string mystring) 
    { 
      // Do stuff 

      // Now Raise an event 
      PublishEvent(); 

      return true; 
    } 

    public Boolean SubscribeToEvent() 
    {  
     IMyApplicationCallback IMAC = OperationContext.Current.GetCallbackChannel<IMyApplicationCallback>(); 
     if (!Callbacklist.Contains(IMAC) 
      Callbacklist.Add(IMAC); 
    } 

    private void PublishEvent() 
    { 
     EventMessage myEM = new EventMessage(); 

     // Populate myEM.Fields 

     Callbacklist.ForEach(delegate(IMyApplicationCallback callback) 
     { callback.EventRaised(myEM); }); 
    } 
} 

的想法是,客户可以选择订阅接收事件。

我在分阶段构建我的应用程序并立即执行回调之前,服务工作正常。对DoSomething()进行的调用做了他们应该做的事情,并立即返回。

现在我已经实现了CallBacks,如果我注释掉DoSomething中的RaiseEvents()行,它会立即返回。

我的客户端代码现在先调用SubscribeToEvent(),然后再次调用DoSomething()。

如果我取消注释并通过调试器进行操作,我会发现DoSomething几乎立即就完成了 - 没有任何延迟。我已经同时在VS2010上运行同一台机器上的客户端& WCF服务。我遵循DoSomething()中的结束语}。

但是,我的客户端中的回调函数未被调用。 1分钟后,终于有人打电话了,我也收到一条错误消息,说明我原来的电话已经超时。所以我改变的app.config减少为10秒,该错误信息是:

"This request operation sent to http://localhost:8732/Design_Time_Addresses/MyApplication/MyAppication did not receive a reply in the configured timeout (00:00:09.987997). The time allotted to this operation may have been a portion of a longer timeout..." 

所以看来有物体挡住了第一个电话的回报;但事件已经提出,因为它最终到达那里。我怀疑这是与锁定/并发模式有关,但我承认,我迷失了一个解决方案。

在客户端我使用了通过添加服务引用生成的代理代码。

服务器端应用程序。配置(仅相关份):

</configuration> 

客户端侧的App.config:

<configuration> 
<system.serviceModel> 
    <bindings> 
     <wsDualHttpBinding> 
      <binding name="WSDualHttpBinding_IPredatorEngine" closeTimeout="00:00:10" 
       openTimeout="00:00:10" receiveTimeout="00:10:00" sendTimeout="00:00:10" 
       bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" 
       maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" 
       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="http://localhost:8732/Design_Time_Addresses/MyApplication/MyApplication/" 
      binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IMyApplication" 
      contract="MyApplication.IMyApplication" name="WSDualHttpBinding_IMyApplication"> 
      <identity> 
       <dns value="localhost" /> 
      </identity> 
     </endpoint> 
    </client> 
</system.serviceModel> 
</configuration> 

我假设我没有配置正确的东西。任何人都可以发现它?

回答

0

经过大量的搜索和反复试验,我发现我需要将SynchronizationContext设置为false。

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple, UseSynchronizationContext=false)] 

我还需要设置客户端代码执行以下操作:

[CallbackBehavior(ConcurrencyMode=ConcurrencyMode.Multiple, UseSynchronizationContext = false)]