最初:
情境:
代码:
[DataContract(IsReference=true)]
public class Message
{
[DataMember]
public string TopicName { get; set; }
[DataMember]
public string EventData { get; set; }
[DataMember]
public SerializableDictionary<string, FuturesLineAsset> FuturesLineDictionary { get; set ; }
}
思想:
父:
public class FuturesAsset
{
public string AssetName { get; set; }
public BindableDictionary<string, FuturesLineAsset> AssetLines { get; private set; }
public FuturesAsset()
{
AssetLines = new BindableDictionary<string, FuturesLineAsset>();
}
public FuturesAsset(string assetName)
{
AssetLines = new BindableDictionary<string, FuturesLineAsset>();
AssetName = assetName;
}
}
子:
public class FuturesLineAsset
{
public string ReferenceAsset { get; set; }
public string MID { get; set; }
public double LivePrice { get; set; }
public DateTime UpdateTime { get; set; }
public DateTime LastContributedTime { get; set; }
public double Spread { get; set; }
public double Correlation { get; set; }
public DateTime Maturity { get; set; }
public double ReferenceCurve { get; set; }
public FuturesLineAsset(string mID, string referenceAsset, double livePrice)
{
MID = mID;
ReferenceAsset = referenceAsset;
ReutersLivePrice = livePrice;
}
}
答案 0 :(得分:19)
此错误可能是由许多事情引起的。虽然在这种情况下这是一个时间问题,但它通常与时间无关,尤其是如果立即收到错误。可能的原因是:
答案 1 :(得分:12)
该例外与循环参考无关,当您尝试通过线路抽取大量数据时,它只是完全超时。
WCF附带的默认值非常低(我相信在WCF 4中已经更改了这些值)。阅读这两篇博客文章,他们应该让您知道如何解决您的服务:
Creating high performance WCF services
How to throttle a Wcf service, help prevent DoS attacks, and maintain Wcf scalability
更新:此外,WCF配置中有许多不同的超时,并且取决于它是您正在谈论的客户端还是服务器,您需要更新不同的超时子句...阅读这个thread关于每个人的意思,你应该能够弄清楚你需要提出哪一个。 或,如果你真的不在乎呼叫是否需要很长时间才能完成,你可以将每个超时设置为int.max。
答案 2 :(得分:3)
从Windows服务主机安装程序的OnStart事件中调用了长时间的初始化过程会出现此问题。通过设置TCP绑定的安全模式和超时来修复。
// Create a channel factory.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.Transport;
b.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
b.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;
b.MaxReceivedMessageSize = 1000000;
b.OpenTimeout = TimeSpan.FromMinutes(2);
b.SendTimeout = TimeSpan.FromMinutes(2);
b.ReceiveTimeout = TimeSpan.FromMinutes(10);
答案 3 :(得分:2)
此问题也可能是由于在您完成使用后未清理WCF客户端。在我们的系统中,我们使用一次性模式并将所有函数调用包装到系统中,以便进行适当的清理和记录。我们使用以下类的版本:
public class WcfWrapper : IDisposable
{
private readonly OperationContextScope _operationContextScope;
private readonly IClientChannel _clientChannel;
public WcfWrapper(IClientChannel clientChannel)
{
_clientChannel = clientChannel;
_operationContextScope = new OperationContextScope(_clientChannel);
}
public void Dispose()
{
_operationContextScope.Dispose();
}
public T Function<T>(Func<T> func)
{
try
{
var result = func();
_clientChannel.Close();
return result;
}
catch (Exception ex)
{
KTrace.Error(ex);
_clientChannel.Abort();
throw;
}
}
public void Procedure(Action action)
{
try
{
action();
_clientChannel.Close();
}
catch (Exception ex)
{
KTrace.Error(ex);
_clientChannel.Abort();
throw;
}
}
}
}
我们在服务中进行的每个WCF调用都是通过定义的接口类完成的,如下所示:
public sealed class WcfLoginManager : ILoginManager
{
private static LoginManagerClient GetWcfClient()
{
return
new LoginManagerClient(
WcfBindingHelper.GetBinding(),
WcfBindingHelper.GetEndpointAddress(ServiceUrls.LoginManagerUri));
}
public LoginResponse Login(LoginRequest request)
{
using(var loginManagerClient = GetWcfClient())
using (var slice = new WcfWrapper(loginManagerClient.InnerChannel))
{
DSTicket ticket;
DSAccount account;
return slice.Function(() => new LoginResponse(loginManagerClient.Login(request.accountName, request.credentials, out ticket, out account), ticket, account));
}
}
}
使用此模式,系统中的所有WCF调用都包含Function或Procedure方法,允许它们首先确保在所有错误上进行日志记录,然后确保在没有错误发生时关闭通道但是在中止时发生异常。最后,正如它在using语句中一样,调用了最终的通道处理。通过这种方式,可以防止由于通道未正确清理而出现的错误,这些错误看起来像这个错误。
答案 4 :(得分:1)
当我返回一个包含IEnumerable集合的对象时,我发生了这个异常,并且在检索其中一个集合成员时发生了异常。此时,在代码中捕获它已经太晚了,并且可能在这种情况下WCF被设计为断开套接字,因为向客户端报告异常也为时已晚,因为它已经开始流式传输结果。
答案 5 :(得分:0)
WCF错误:
套接字连接已中止。这可能是由错误引起的 处理您的消息或超过接收超时 远程主机或底层网络资源问题。本地套接字 超时是......
报告的超时非常接近1分钟(例如00:00:59.9680000
)或1分钟(即00:01:00
)可能是由于邮件太大而导致exceeding the settings for the binding。
这可以通过增加配置文件中的值来修复,例如:
<binding name="MyWcfBinding"
maxReceivedMessageSize="10000000"
maxBufferSize="10000000"
maxBufferPoolSize="10000000" />
(仅限示例值,您可能需要调整它们)。
答案 6 :(得分:0)
在我的情况下,我试图用net tcp实例化Wcf。因此,如果在web.config的绑定部分中,您将“ netTcpBinding”配置为这样
<bindings>
<netTcpBinding>
<binding name="bindingName" closeTimeout="01:10:00" openTimeout="01:10:00" receiveTimeout="01:10:00" sendTimeout="01:10:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="10" maxReceivedMessageSize="2147483647" portSharingEnabled="true">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="16384"/>
<reliableSession ordered="true" inactivityTimeout="01:10:00" enabled="false"/>
<security mode="None"/>
</binding>
</netTcpBinding>
</bindings>
然后,您需要使用服务接口的名称空间配置服务部分,以使用合同属性定义端点,并放置baseAddres,类似这样
<services>
<service behaviorConfiguration="sgiBehavior" name="Enterprise.Tecnic.SGI.OP.Wcf.OP">
<endpoint address="" behaviorConfiguration="endPointBehavior" binding="webHttpBinding" bindingConfiguration="BindingWebHttp" name="endPointHttp" contract="Enterprise.Tecnic.SGI.OP.Interface.IOP"/>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
<endpoint address="" binding="netTcpBinding" bindingConfiguration="bindingName"
name="EndpointNetTcp" contract="Enterprise.Tecnic.SGI.OP.Interface.IOP" />
<host>
<baseAddresses>
<!-- <add baseAddress="http://localhost:61217/OP.svc"/> -->
<add baseAddress="http://www.Enterprise.com/Tecnic/SGI/OP/" />
<add baseAddress="net.tcp://www.Enterprise.com/Tecnic/SGI/OP/" />
</baseAddresses>
</host>
</service>
</services>
我花了两天时间解决这个问题,但这是唯一对我有用的东西。