为什么WCF ServiceHost一旦超出范围就保持打开状态?

时间:2012-07-13 16:23:31

标签: .net multithreading wcf self-hosting servicehost

我只是整理了我的一些WCF(自托管)代码,并意识到我的ServiceHost对象在最初设置后超出了范围,但我仍然可以连接到它。

public void StartMyService()
{
    var host = new ServiceHost(typeof(MyService), new Uri("http://localhost:8000/MyService"));
    host.Open();
}

如果我再次调用它并重新实例化并再次尝试打开它,我会收到错误消息,说已经有东西连接到端点了。它只会在应用程序关闭时立即释放。

我只能假设对Open()的调用在较低级别执行某些操作以使其以现在非托管方式保持打开状态。但是,除非我完全误解了这里的内容,否则我找不到任何相关信息。

考虑到这一点,现在连接现在仍然是开放的,这似乎是不对的,但我无法在不杀死应用程序的情况下回到它(关闭等)。或者这甚至不重要,如果它没有伤害任何东西我可以一直打开它吗?

更新:所以我接受了Eiver的答案,因为它解释了我原来的问题,即为什么它在超出范围后仍保持开放状态。但是,我现在想知道关于这个的一些事情(或者我对线程的经验不足)。首先,只要它是公开的,我就会对这个问题感到困扰。如果通过将线程保持在范围内来某种方式来访问线程,它是否会有所帮助。也许,像这样设置(并且从不调用close)会使调用代码变得简单(即不必保留引用),我甚至可以将它包装在静态方法中,以实现更简单的调用。所有声音都有点躲闪......嗯!

更新2 :所以,我知道这样做并不好,因为这意味着我不再控制主机及其启动的线程。所以我把它全部包装成一个Singleton,让我能够在任何时候访问主机(对于错误,事件,在同一端点上关闭/重新打开等)并使调用非常简单(就像一个简单的静态方法)呼叫)。

3 个答案:

答案 0 :(得分:1)

并非所有超出范围的内容都会终止。如果一个类产生另一个线程(我确信WCF会这样做),即使对创建它的类的引用被垃圾收集,该线程也可能存在。

您可能需要调用host.Close()

答案 1 :(得分:1)

我的猜测是使用StartMyService()方法的Class仍处于活动状态。如果你像这样编码它会做(我认为)它应该做的事情。留下注释掉的代码,因为我认为这是一种更简洁的方式来启动服务并让它超出范围。

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("**** Console Based WCF Host *****");

            //using (ServiceHost serviceHost = new ServiceHost(typeof(MagicEightBallService)))
            //{
            //    serviceHost.Open();
            //    Console.WriteLine("The service is running");
            //    Console.ReadLine();
            //}
            using (MySvc ms = new MySvc())
            {
                ms.StartMyService();
            }
            Console.ReadLine();
        }

        public class MySvc: IDisposable
        {
            ServiceHost serviceHost;
            public void StartMyService()
            {
                serviceHost = new ServiceHost(typeof(MagicEightBallService));
                serviceHost.Open();
            }
            public void Dispose() 
            {
                // the class needs to clean up after itself
                serviceHost.Close();
            }
            public MySvc() { }
        }
    }

答案 2 :(得分:0)

在尝试访问它之前,可能没有收集到它。