使用匿名方法关闭WCF连接

3

在我们的项目中,我们使用以下代码进行 WCF 调用。

// In generated Proxy we have..
public static ICustomer Customer
{
 get
  {
    ChannelFactory<ICustomer> factory = new ChannelFactory<ICustomer>("Customer");
    factory.Endpoint.Behaviors.Add((System.ServiceModel.Description.IEndpointBehavior)new ClientMessageInjector());
    ICustomer channel = factory.CreateChannel();
    return channel;
  }
}

我们有一个服务代理类,其中包含像以下这些方法:
public static Datatable GetCustomerDetails(int id)
{
  return Services.Customer.GetCustomerDetails(id);
} 

public static void .SaveCustomerDetails (int id)
{
  Services.Customer.SaveCustomerDetails(id) ;
}

我们使用IT技术来进行商务通话等操作。

最近我们发现需要“关闭”wcf连接,因此我们正在尝试找到一种方法,在不太改变开发人员代码的情况下完成这一点。

请提供一些建议,以帮助我们实现这个目标。

6个回答

6
这种情况下被认可的“最佳实践”是类似于以下内容:
// create your client
ICustomer channel = CreateCustomerClient();

try
{
   // use it
   channel.GetCustomerDetails() ....

   (more calls)

   // close it
   channel.Close();
}
catch(CommunicationException commEx)
{
   // a CommunicationException probably indicates something went wrong 
   // when closing the channel --> abort it
   channel.Abort();
}

通常情况下,由于该通道还实现了“IDisposable”,您可能会想要仅将其放入其中。
using(ICustomer channel = CreateCustomerChannel()) 
{
   // use it
}

block - 不幸的是,这可能会失败,因为在尝试在您的通道上调用.Close()时,很有可能会得到另一个异常(在这种情况下未处理)。

我们这里的主持人Marc Gravell在这个话题上有一篇有趣的博客文章(不要使用using),提供了一个优雅的解决方案。

Marc


1

在当前的方法中,您还泄漏了ChannelFactory<T>对象。您也应该关闭这些对象。如果您使用ChannelFactory<T>上的静态CreateChannel方法,则在客户端关闭时,工厂将自动关闭,从而可以解决此问题。不幸的是,静态CreateChannel(string endpointConfigurationName)重载是受保护的,因此您需要子类化ChannelFactory<T>才能调用它。(总体来说,这可能并不那么糟糕。)

现在,如果您想要一个通道的“自动关闭”行为,并且您正在使用会话协定(SessionMode = SessionMode.Required),则可以在[OperationContract]属性中将所有服务操作标记为“IsInitiating = true, IsTerminating = true”。请注意,这将防止您能够使用相同的ICustomer代理调用多个操作。如果可用,这可能是最简单的选项。

关于您的一般方法,一个属性做太多工作是不被认为是良好的设计,特别是当它涉及构建新的(昂贵的)对象和访问网络时。WCF代理是很好的抽象,看起来像简单的接口实现,但它们不是无状态的,必须适当地进行管理。

0
正确关闭连接的方式是将客户端放入using块中,或将关闭操作放在finally语句中。否则,它们只有在没有抛出异常时才会被关闭。

2
在WCF客户端的情况下并非如此!由于调用.Close()方法时很有可能会出现异常,因此仅仅将其放在using()块中并不是推荐的最佳实践。 - marc_s
这是正确的。通常的解决方案是将其封装在实现了IDisposable接口且在Dispose中有try/catch的对象中。这样,您就可以安全地使用using。我会发帖子,但我知道它已经出现在其他问题中。如果没有这个,你就必须在finally中使用try/catch,这个方法可行但很棘手。 - Steven Sudit
警惕:如果using的Finally块中的Close抛出异常,请注意检查它们。 - BozoJoe

0

这个问题中的信息也可能会有所帮助。


0

很不幸,我们使用生成的代理方法返回通道,并在许多地方使用它。因此,我认为有一些方法可以“扩展”通道并在调用后关闭连接(使用扩展方法)。


请编辑您的问题,而不是添加答案。如果您无法访问原始帐户,则单击页面底部的“联系我们”链接,请求合并帐户。 - John Saunders

0
不要每次创建通道时都创建一个新的通道工厂。从性能角度来看,这是可怕的!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接