我正在重构一个通过wcf进行进程间通信的大型程序。由于客户端可以直接访问服务接口,因此使用channelfactory来创建通道,因此不需要额外的客户端服务存根。通信由许多高频请求的大消息组成(目前使用的是NetTcpBinding,我正在考虑切换到NetNamedPipeBinding)。
我的问题是关于创建/关闭频道与创建/关闭channelfactory之间的区别。更确切地说:channelfactory创建了一个频道。现在,关于单个请求:我应该创建和关闭channelfactory,还有与单个请求相关的通道(参见解决方案2),或者在性能方面更安全/更好只创建/关闭与单个请求相关的通道,并为多个请求保持channelfactory打开(请参阅解决方案编号1)。
1)
//set up the channel factory right when I start the whole applicaton
ChannelFactory<IMyService> cf = new ChannelFactory<IMyService>();
//call this trillion of times over time period of hours whenever I want to make a request to the service; channel factory stays open for the whole time
try
{
IMyService myService = cf.CreateChannel();
var returnedStuff = myService.DoStuff();
((IClientChannel)myService).Close();
}
catch ...
//close the channel factory when I stop the whole application
cf.Close();
2)
//call this trillion of times over time period of hours whenever I want to make a request to the service
try
{
ChannelFactory<IMyService> cf = new ChannelFactory<IMyService>();
IMyService myService = cf.CreateChannel();
var returnedStuff = myService.DoStuff();
cf.Close();
}
catch ...
有什么实际差异?做正确的方法是什么?还有更好的选择吗?
答案 0 :(得分:2)
创建频道工厂最多可能需要70毫秒(在我正在处理的应用程序中)。 创建渠道(相比之下,来自现有渠道工厂的渠道相对较快)。如果您的客户端通常使用相同的凭据与主机通信,则应考虑为每个使用的服务接口缓存channelfactory。如果这样做,您将看到显着的性能改进。在您的问题中,这将与您描述的第二个选项更紧密相关。
Darin Damitrov在这里做了一篇有趣的帖子: -
答案 1 :(得分:0)
你应该这样做的方式是:
ChannelFactory<IMyService> channelFactory = null;
try
{
channelFactory =
new ChannelFactory<IMyService>();
channelFactory.Open();
// Do work...
channelFactory.Close();
}
catch (CommunicationException)
{
if (channelFactory != null)
{
channelFactory.Abort();
}
}
catch (TimeoutException)
{
if (channelFactory != null)
{
channelFactory.Abort();
}
}
catch (Exception)
{
if (channelFactory != null)
{
channelFactory.Abort();
}
throw;
}
这背后的主要原因是如果你在ChannelFactory上调用Dispose(),而ChannelFactory又调用Close(),如果底层Channel处于中止状态,则会抛出异常。
答案 2 :(得分:0)
对我原来的问题不是一个直截了当的答案,但我已经看到ChannelFactory上有静态的CreateChannel方法,可以用来创建通道。我现在使用这种方法来创建通道,因此,我不再需要处理channelfactory实例。因此,我在使用静态工厂方法的每个请求之前创建clientchannel,然后关闭它(通道)。