C# WCF 关闭通道并使用函数 Func
这就是重点,我有一个 WCF 服务,它现在正在工作。所以我开始在客户端工作。当应用程序运行时,出现异常:超时。所以我开始阅读,有很多关于如何保持连接活动的示例,但是,我也发现最好的方法是创建通道,使用它并处置它。老实说,我喜欢这样。因此,现在阅读有关关闭频道的最佳方法的信息,有两个链接可能对任何需要它们的人有用:
在第一个链接中,这是示例:
IIdentityService _identitySvc;
...
if (_identitySvc != null)
{
((IClientChannel)_identitySvc).Close();
((IDisposable)_identitySvc).Dispose();
_identitySvc = null;
}
因此,如果通道不为 null,则关闭、处置并分配 null。但我有一个小问题。在此示例中,通道有一个 .Close() 方法,但在我的例子中,智能感知未显示 Close() 方法。它只存在于工厂对象中。所以我相信我必须写它。但是,在具有合同或实现它的类的接口中?而且,这个方法应该做什么??
现在,下一个链接,这是我以前从未尝试过的东西。 Func
。读完目标后,这很有趣。它创建了一个函数,使用 lambda 表达式创建通道、使用它、关闭它并处置它。此示例像 Using()
语句一样实现该函数。这真的很好,而且是一个很好的改进。但是,我需要一点帮助,说实话,我无法理解该功能,因此,专家的一些解释将非常有用。这是功能:
TReturn UseService<TChannel, TReturn>(Func<TChannel, TReturn> code)
{
var chanFactory = GetCachedFactory<TChannel>();
TChannel channel = chanFactory.CreateChannel();
bool error = true;
try {
TReturn result = code(channel);
((IClientChannel)channel).Close();
error = false;
return result;
}
finally {
if (error) {
((IClientChannel)channel).Abort();
}
}
}
这就是使用方式:
int a = 1;
int b = 2;
int sum = UseService((ICalculator calc) => calc.Add(a, b));
Console.WriteLine(sum);
是的,我认为真的非常好,我想了解它以便在我的项目中使用它。
和往常一样,我希望这对很多人有帮助。
This is the point, I have a WCF service, it is working now. So I begin to work on the client side. And when the application was running, then an exception showed up: timeout. So I began to read, there are many examples about how to keep the connection alive, but, also I found that the best way, is create channel, use it, and dispose it. And honestly, I liked that. So, now reading about the best way to close the channel, there are two links that could be useful to anybody who needs them:
1. Clean up clients, the right way
In the first link, this is the example:
IIdentityService _identitySvc;
...
if (_identitySvc != null)
{
((IClientChannel)_identitySvc).Close();
((IDisposable)_identitySvc).Dispose();
_identitySvc = null;
}
So, if the channel is not null, then is closed, disposed, and assign null. But I have a little question. In this example the channel has a .Close() method, but, in my case, intellisense is not showing a Close() method. It only exists in the factory object. So I believe I have to write it. But, in the interface that has the contracts or the class that implemets it??. And, what should be doing this method??.
Now, the next link, this has something I haven't try before. Func<T>
. And after reading the goal, it's quite interesting. It creates a funcion that with lambdas creates the channel, uses it, closes it, and dipose it. This example implements that function like a Using()
statement. It's really good, and a excellent improvement. But, I need a little help, to be honest, I can't understand the function, so, a little explanatino from an expert will be very useful. This is the function:
TReturn UseService<TChannel, TReturn>(Func<TChannel, TReturn> code)
{
var chanFactory = GetCachedFactory<TChannel>();
TChannel channel = chanFactory.CreateChannel();
bool error = true;
try {
TReturn result = code(channel);
((IClientChannel)channel).Close();
error = false;
return result;
}
finally {
if (error) {
((IClientChannel)channel).Abort();
}
}
}
And this is how is being used:
int a = 1;
int b = 2;
int sum = UseService((ICalculator calc) => calc.Add(a, b));
Console.WriteLine(sum);
Yep, I think is really, really good, I'd like to understand it to use it in the project I have.
And, like always, I hope this could be helpful to a lot of people.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
UseService 方法接受委托,该委托使用通道发送请求。委托有一个参数和一个返回值。您可以将对 WCF 服务的调用放在委托中。
在 UseService 中,它创建通道并将通道传递给委托,该委托应该由您提供。通话结束后,关闭通道。
the UseService method accepts a delegate, which uses the channel to send request. The delegate has a parameter and a return value. You can put the call to WCF service in the delegate.
And in the UseService, it creates the channel and pass the channel to the delegate, which should be provided by you. After finishing the call, it closes the channel.
代理对象不仅仅实现您的合同 - 它还实现 IClientChannel< /a> 允许控制代理生命周期
第一个示例中的代码不可靠 - 如果通道已经损坏(例如,服务在基于会话的交互中已关闭),它将泄漏。正如您在第二个版本中所看到的,如果出现错误,它会在代理上调用 Abort,这仍然会清理客户端
您也可以使用扩展方法来执行此操作,如下所示:
但是,此方法的使用有点麻烦
但是,如果您创建自己的代理接口来扩展您的合约和 IClientChannel,则可以使其更加优雅
The proxy object implements more than just your contract - it also implements IClientChannel which allows control of the proxy lifetime
The code in the first example is not reliable - it will leak if the channel is already busted (e.g. the service has gone down in a session based interaction). As you can see in the second version, in the case of an error it calls Abort on the proxy which still cleans up the client side
You can also do this with an extension method as follows:
However, the usage of this is a little cumbersome
But you can make this more elegant if you make your own proxy interface that extends both your contract and IClientChannel
为了回答 Jason 的回答中评论中留下的问题,GetCachedFactory 的一个简单示例可能如下所示。该示例通过在配置文件中查找“Contract”属性等于工厂要创建的服务的 ConfigurationName 的端点来查找要创建的端点。
不过,更好的解决方案是让 IoC 容器为您管理客户端的创建。例如,使用 autofac 会出现以下情况。首先,您需要像这样注册服务:
其中“WSHttpBinding_ICalculator”是配置文件中端点的名称。然后您可以像这样使用该服务:
To answer the question left in the comment in Jason's answer, a simple example of GetCachedFactory may look like the below. The example looks up the endpoint to create by finding the endpoint in the config file with the "Contract" attribute equal to the ConfigurationName of the service the factory is to create.
A better solution though is to let an IoC container manage the creation of the client for you. For example, using autofac it would like the following. First you need to register the service like so:
Where "WSHttpBinding_ICalculator" is the name of the endpoint in the config file. Then later you can use the service like so: