如何确保您没有收到 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,请确保MaxReceivedMessageSizeMaxBufferSize的值相同。经过几个小时的努力,我刚刚以这种方式解决了故障状态问题,并认为如果对某人有帮助,我会在此处发布。

【讨论】:

这个问题很棘手!你为我解决了它并节省了我几个小时。谢谢【参考方案4】:

此错误也可能是由于使用 OperationContract 属性标记的方法为零。这是我在构建新服务并进行长期测试时遇到的问题。

【讨论】:

【参考方案5】:

与 Ryan Rodemoyer 的回答类似,我发现当合同上的 UriTemplate 无效时,您会收到此错误。就我而言,我两次使用相同的参数。例如:

/Root/Name/Name

【讨论】:

以上是关于如何确保您没有收到 WCF 故障状态异常?的主要内容,如果未能解决你的问题,请参考以下文章

WCF 的“使用”语句中的异常未正确关闭连接。如何关闭有故障的 WCF 客户端连接或有异常的连接?

WCF 无法用于通信,因为它处于故障状态

如何解决此 WIF/WCF 异常?

使用 WCF 客户端访问 RESTful 服务时访问 HTTP 状态代码

WCF 回调通道出现故障

WCF 给出不安全或不正确安全的故障错误