c# - WCF 服务主机关闭被打开的 session 阻止并且设置 receiveTimeout 没有帮助

标签 c# .net wcf iis-7 servicehost

我需要我的 WAS 托管服务(PerCall、Concurrency.Multiple)正常关闭/回收,但任何不活动(但打开)的客户端代理将阻止服务正常关闭。

我原以为 receiveTimout 会启动并丢弃不活动的 session ,但它看起来不像那样工作。

IIS/WAS 回收将调用 ServiceHost.BeginClose,关闭超时设置为 TimeSpan.MaxValue。

我需要使用 netTcpBinding 允许长期存在的客户端代理(我无法真正控制),因为吞吐量和低延迟是必须的。

我已经重现了下面的问题,很乐意提供任何解决方法和有关该问题的帮助。

using System;
using System.ServiceModel;

namespace Test
{
    [ServiceContract(Name = "MyService", SessionMode = SessionMode.Allowed)]    
    public interface IHelloWorldService
    {
        [OperationContract]
        void PrintHelloWorld();
    }

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class HellowWorldService : IHelloWorldService
    {
        [OperationBehavior]
        public void PrintHelloWorld()
        {
            Console.WriteLine("Hello world!");
        }
    }

    public class ThaProgram
    {
        static void Main(string[] args)
        {
            const string ServiceAddress = "net.tcp://localhost:12345/HelloWorld";            
            var netTcpBinding = new NetTcpBinding(SecurityMode.None, false);
            netTcpBinding.ReceiveTimeout = TimeSpan.FromSeconds(3);
            var serviceHost = new ServiceHost(typeof(HellowWorldService), new Uri("net.tcp://localhost:12345"));
            serviceHost.AddServiceEndpoint(typeof(IHelloWorldService), netTcpBinding, ServiceAddress);

            serviceHost.Open();
            Console.WriteLine("Service host state: {0}", serviceHost.State);

            netTcpBinding.ReceiveTimeout = TimeSpan.FromSeconds(10);
            var channel = new ChannelFactory<IHelloWorldService>(netTcpBinding, ServiceAddress).CreateChannel();
            channel.PrintHelloWorld();

            // Uncomment to make everything work (then the session will be closed before the service enters the closing state)
            // Thread.Sleep(4000);

            // Simulate application pool shutdown
            var asyncResult = serviceHost.BeginClose(TimeSpan.MaxValue, null, null);
            Console.WriteLine("Service host state: {0}", serviceHost.State);
            serviceHost.EndClose(asyncResult);
            Console.WriteLine("Service host state: {0}", serviceHost.State);

            Console.WriteLine("Hit Enter to close the application");
            Console.ReadLine();
        }
    }
}

最佳答案

奇怪的是 TCP-bound *WCF 服务主机* 无法随时切断连接,这就是 TCP 与命名管道不同的优点。

无论如何,我喜欢使用的一个好模式是将所有服务主机操作包装在一个单独的 .net AppDomain 中。它是在这个辅助 AppDomain 中托管服务,而不是 Primary AppDomain。把它想象成一个沙箱。然后,当您希望关闭时,您可以使用正常的服务主机关闭方法关闭,然后让主应用程序域执行 AppDomain.Unload() 这不仅是内存清理的好方法 而且切断所有那些没有正确关闭的讨厌的客户端

这种模式在命名管道 WCF 中是绝对必须的,因为客户端可以阻止服务器再次启动,正如我在之前的项目中发现的那样。 (由于孤立连接)

希望一切顺利

关于c# - WCF 服务主机关闭被打开的 session 阻止并且设置 receiveTimeout 没有帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5792052/

相关文章:

c# - 是否可以在 SaveChanges 之后停止 Entity Framework "fixing up"关系?

WCF netmsmq 绑定(bind)。如果 MSMQ 不可用,请在客户端上重试

wcf - iis 8 不接受 IP 地址作为主机名

.net - Chunky 界面含义

c# - 无窗口 WPF 应用程序

C# XAML 拉伸(stretch)网格以适合 listViewItem

c# - Google Speech API v2 结果为空白

.NET:缺少必需的配置设置时抛出哪个异常?

wcf - 使用 COM 优于 WCF 的优势

c# - 预检请求返回 404 Not Found for Controllers in an Area