【问题标题】:Why does WCF ServiceHost stay open once out of scope?为什么 WCF ServiceHost 一旦超出范围就保持打开状态?
【发布时间】:2012-07-13 16:23:30
【问题描述】:

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

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

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

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

想一想,连接现在仍然打开,但我无法在不终止应用程序的情况下返回它(关闭等),这似乎并不正确。或者也许这甚至都没有关系,如果它不伤害任何东西,我可以让它一直打开?

更新:所以我接受了 Eiver 的回答,因为它解释了我最初的问题,即为什么它在超出范围后仍保持打开状态。但是,我现在想知道一些关于此的事情(或者我可能对线程缺乏经验)。首先,只要它是开放的,我是否会为此烦恼,这一切都是正确的。如果有某种方法可以通过将线程保持在范围内来访问线程,它甚至会有所帮助。也许,像这样设置它(并且从不调用 close)使调用代码变得简单(即不必保留引用),我什至可以将它包装在一个静态方法中以进行更简单的调用。听起来有点躲闪……嗯!

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

【问题讨论】:

  • 我猜它只是还没有被垃圾收集。在该方法完成后尝试运行 GC.Collect() 并查看它是否仍然存在。
  • 试过了,还活蹦乱跳的。

标签: .net multithreading wcf self-hosting servicehost


【解决方案1】:

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

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

【讨论】:

【解决方案2】:

我的猜测是带有 StartMyService() 方法的类仍然存在。如果你这样编码,它会做(我认为)它应该做的事情。留下注释掉的代码,因为我认为这是启动服务并让它超出范围的一种更清洁的方式。

    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() { }
        }
    }

【讨论】:

  • 谢谢,是的,当然明确关闭它会关闭它,但更多的是一个问题,即在对它的引用超出范围后它为什么(更多如何)保持打开状态。另一件事(要挑剔),您在像这样处理时必须小心,因为 Open 调用期间的任何错误也会在处理时导致错误(并且可能意味着丢失打开的重要错误细节)。见danrigsby.com/blog/index.php/2008/02/26/…
  • 看可以回答。我的猜测是带有 StartMyService() 方法的类仍然存在。
【解决方案3】:

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

【讨论】:

  • 我也这么认为,但恢复它很好,当我回忆起 Open() 方法时,我得到了错误。另外我等了很长时间,它仍然是开放的。
猜你喜欢
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-10
  • 2019-03-16
  • 2010-10-23
  • 2015-11-05
相关资源
最近更新 更多