C# 为什么我的WCF客户端在调用WCF服务器中引发事件的方法后超时?
我在Windows服务中托管了一个WCF服务。WCF服务中有一个方法将引发Windows服务订阅的事件。当引发事件且Windows服务捕获该事件时,Windows服务调用另一个WCF方法向所有连接的客户端发送消息。出于某种原因,当我让所有这些按此顺序发生时,会抛出一个错误:C# 为什么我的WCF客户端在调用WCF服务器中引发事件的方法后超时?,c#,.net,wcf,events,windows-services,C#,.net,Wcf,Events,Windows Services,我在Windows服务中托管了一个WCF服务。WCF服务中有一个方法将引发Windows服务订阅的事件。当引发事件且Windows服务捕获该事件时,Windows服务调用另一个WCF方法向所有连接的客户端发送消息。出于某种原因,当我让所有这些按此顺序发生时,会抛出一个错误: This request operation sent to http://localhost:8731/Design_Time_Addresses/WCF/WCFService/ did not receive a rep
This request operation sent to http://localhost:8731/Design_Time_Addresses/WCF/WCFService/ did not receive a reply within the configured timeout (00:00:29.9939996)....
以下是WCF服务的相关代码:
public event EventHandler<CustomEventArgs> CustomEvent;
private static readonly List<IMessageCallback> subscribers = new List<IMessageCallback>();
public void SendMessageToClients(string msgType, string message)
{
subscribers.ForEach(delegate(IMessageCallback callback)
{
if (((ICommunicationObject)callback).State == CommunicationState.Opened)
{
callback.OnMessageReceived(msgType, message, DateTime.Now);
}
else
{
subscribers.Remove(callback);
}
});
}
public bool messageHost()
{
try
{
if (CustomEvent != null)
CustomEvent(null, new CustomEventArgs());
return true;
}
catch
{
return false;
}
}
以下是客户端配置:
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="WSDualHttpBinding_IWCFService" closeTimeout="00:00:10"
openTimeout="00:00:10" receiveTimeout="00:10:00" sendTimeout="00:00:30"
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="http://localhost:8731/Design_Time_Addresses/WCF/WCFService/"
binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IWCFService"
contract="WCFService.IWCFService" name="WSDualHttpBinding_IWCFService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
以及服务配置:
<system.serviceModel>
<services>
<service name="WCF.WCFService" behaviorConfiguration="WCFBehavior">
<endpoint address="" binding="wsDualHttpBinding" contract="WCF.IWCFService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint
address="mex"
binding="mexHttpBinding"
bindingConfiguration=""
contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/Design_Time_Addresses/WCF/WCFService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
这里的症状向我暗示,可能是由于同步上下文(默认情况下WCF尊重同步上下文)而发生了死锁。含义:外部消息正在等待对上下文的访问,但它本身就是现有上下文正在等待的东西
最简单的调查方法是在工作线程上执行向外消息:
ThreadPool.QueueUserWorkItem(delegate {
wcfObj.messageHost();
});
我相信您也可以配置WCF来改变它如何接近同步上下文,但我不记得您如何发布WCF配置:客户端、服务器这听起来很有道理。我尝试在客户端中使用您的代码,但似乎客户端在冻结之前会更进一步,然后抛出超时错误。关于同步上下文,您完全正确。我发现这个链接很好地解释了这一点:@Brian-cool-看起来像CallbackBehavior
和ConcurrencyMode
是我记忆中的配置开关
<system.serviceModel>
<services>
<service name="WCF.WCFService" behaviorConfiguration="WCFBehavior">
<endpoint address="" binding="wsDualHttpBinding" contract="WCF.IWCFService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint
address="mex"
binding="mexHttpBinding"
bindingConfiguration=""
contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/Design_Time_Addresses/WCF/WCFService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
ThreadPool.QueueUserWorkItem(delegate {
wcfObj.messageHost();
});