如何确保您没有收到 WCF 故障状态异常?
Posted
技术标签:
【中文标题】如何确保您没有收到 WCF 故障状态异常?【英文标题】:How to make sure you don't get WCF Faulted state exception? 【发布时间】:2010-10-06 13:18:56 【问题描述】:我遇到了这个异常:
通讯对象, System.ServiceModel.Channels.ServiceChannel, 不能用于通讯 因为它处于故障状态。
WCF 服务使用默认的 wsHttpBinding。无论我在哪里使用 WCF,我都以以下方式使用它:
using (var proxy = new CAGDashboardServiceClient())
proxy.Open();
var result = proxy.GetSiteForRegion(ddlRegions.SelectedValue);
ddlSites.DataSource = result;
ddlSites.DataBind();
proxy.Close();
消息中显示的错误行似乎在最后一个 proxy.close 之后。不知道发生了什么。我正在从 Visual Studio 08 中启动该服务。
这是跟踪信息:
The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
Server stack trace:
at System.ServiceModel.Channels.CommunicationObject.Close(TimeSpan timeout)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at System.ServiceModel.ICommunicationObject.Close(TimeSpan timeout)
at System.ServiceModel.ClientBase`1.System.ServiceModel.ICommunicationObject.Close(TimeSpan timeout)
at System.ServiceModel.ClientBase`1.Close()
at System.ServiceModel.ClientBase`1.System.IDisposable.Dispose()
at CAGDashboard.UserControls.ucVolunteerCRUDGrid.ddlRegions_SelectedIndexChanged(Object sender, EventArgs e) in C:\Documents and Settings\rballalx\My Documents\Visual Studio 2008\Projects\DashboardCAG\CAGDashboard\UserControls\ucVolunteerCRUDGrid.ascx.cs:line 81
at System.Web.UI.WebControls.ListControl.OnSelectedIndexChanged(EventArgs e)
at System.Web.UI.WebControls.DropDownList.RaisePostDataChangedEvent()
at System.Web.UI.WebControls.DropDownList.System.Web.UI.IPostBackDataHandler.RaisePostDataChangedEvent()
at System.Web.UI.Page.RaiseChangedEvents()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
【问题讨论】:
【参考方案1】:You should avoid putting client proxies in using
blocks.
【讨论】:
谢谢!!我也试过不使用语句......没有成功:( 我写了一些包装代码来帮助 WCF + using block issue nimtug.org/blogs/damien-mcgivern/archive/2009/05/26/… 但它是 IDisposable。 “使用”是最佳实践! 不希望使用,因为它 (1) 可以隐藏错误并且 (2) 某些异常(例如通信异常)需要您调用“Abort”来释放资源。如果您的频道正确关闭,您在这里没有问题,但如果没有,您可以让资源保持打开状态,直到垃圾收集器开始清理它们。这就是为什么 try-catch 更好。您可以专门调用需要解决的异常,并且不会像使用 try-finally(using 语句)那样掩盖错误。 这是由 WCF 团队 IMO 设计的非常糟糕的设计。【参考方案2】:更新:
这个linked answer describes a cleaner, simpler way of doing the same thing with C# syntax.
原帖
这是微软推荐的处理 WCF 客户端调用的方法:
更多详情请见:Expected Exceptions
try
...
double result = client.Add(value1, value2);
...
client.Close();
catch (TimeoutException exception)
Console.WriteLine("Got 0", exception.GetType());
client.Abort();
catch (CommunicationException exception)
Console.WriteLine("Got 0", exception.GetType());
client.Abort();
其他信息
似乎有很多人在 WCF 上问这个问题,以至于微软甚至创建了一个专门的示例来演示如何处理异常:
c:\WF_WCF_Samples\WCF\Basic\Client\ExpectedExceptions\CS\client
下载示例: C# 或 VB
考虑到involving the using statement、(heated?) Internal discussions 和threads 在这个问题上存在很多问题,我不会浪费时间尝试成为代码牛仔并找到更清洁的方法。我将把它吸干,并为我的服务器应用程序以这种冗长(但受信任)的方式实现 WCF 客户端。
【讨论】:
关于 SO 的以下问题列出了例外情况和如何处理它们的最佳实践:***.com/questions/6130331/…【参考方案3】:如果传输模式为Buffered,请确保MaxReceivedMessageSize和MaxBufferSize的值相同。经过几个小时的努力,我刚刚以这种方式解决了故障状态问题,并认为如果对某人有帮助,我会在此处发布。
【讨论】:
这个问题很棘手!你为我解决了它并节省了我几个小时。谢谢【参考方案4】:此错误也可能是由于使用 OperationContract 属性标记的方法为零。这是我在构建新服务并进行长期测试时遇到的问题。
【讨论】:
【参考方案5】:与 Ryan Rodemoyer 的回答类似,我发现当合同上的 UriTemplate 无效时,您会收到此错误。就我而言,我两次使用相同的参数。例如:
/Root/Name/Name
【讨论】:
以上是关于如何确保您没有收到 WCF 故障状态异常?的主要内容,如果未能解决你的问题,请参考以下文章
WCF 的“使用”语句中的异常未正确关闭连接。如何关闭有故障的 WCF 客户端连接或有异常的连接?