【问题标题】:Timer inside a WCF Singleton hosted in a Windows Service (over webHttpBinding) dies unexpectedly托管在 Windows 服务中的 WCF 单例中的计时器(通过 webHttpBinding)意外死亡
【发布时间】:2011-08-14 12:38:52
【问题描述】:

我有一个托管在 Windows 服务中的 WCF 服务(在本地系统下运行)。我在里面运行一个 System.Timer。初始化 Timer 的操作 o1 在 webHttpBinding 上的 http 端点上声明。 我为 System.ServiceModel 启用了跟踪,并从 .svcLog 文件中检查了操作 o1 的侦听持续时间。它表明,在运行大约 20 小时后,http 端点处的侦听刚刚停止。

我认为这是因为没有传入消息到达该端点。这里的问题是监听停止,我的计时器(在特定操作 o1 中初始化)也停止了!

有没有推荐的方法来让监听器和计时器长时间保持正常状态? 我们可以定期 ping o1 操作以将其保存在内存中吗?

另外,我在操作 o1 中初始化的计时器变量是一个实例变量,即使监听器关闭,这个变量是否应该在内存中(WCF 是单例)??

非常感谢。

代码摘录-

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class SchedulerWindows : ISchedulerWindows
{
    ///.........all instance variables.....
    DataTimer timer = null; /**DataTimer wraps a System.Timers timer variable**/
    public List<DataTimer> timersInService = new List<DataTimer>();
    public ISchedulerWindows.o1(string s1, string s2, /*********/)
    {
     //..........//
     timer = new DataTimer();
    }
}

public class DataTimer
    {

        /****Newly introduced System.Threading.Timer, previously I was using        System.Timers.Timer which was dying****/

        public System.Threading.Timer thTimer;
        private static readonly object dbAccessLock = new object();
        private static readonly object thCallbackLock = new object();

        public DataTimer()
        {
        }

        public DataTimer(/************/)
        {            
            TimerCallback timerDelegate = new TimerCallback(this.WorkMethod);
            EventLogLogger l = new EventLogLogger();
            //l.LogMessage("setting up timer ");
            thTimer = new Timer(this.WorkMethod, null, 0, period);
        }
...
}

编辑:从 System.Timers 命名空间更改为 System.Threading 命名空间并增加定时间隔为我修复了它。计时器变量不再消失。

【问题讨论】:

    标签: wcf service timer window webhttpbinding


    【解决方案1】:

    您的问题最可能的原因是InstanceContextMode。如果您希望您的服务实例始终在内存中,您应该使用 Single。您可能有 PerSession 或 PerCall,这可以解释为什么您的计时器正在消失。您提到您的服务是单例的,但症状非常可疑。服务实例会一直保留在内存中,直到您关闭主机。

    [ServiceBehavior(
             ConcurrencyMode = ConcurrencyMode.Multiple, 
             InstanceContextMode = InstanceContextMode.Single
    )]
    

    来自WCF instance management

    单例服务永远存在,并且只会在 主机关闭。单例仅在宿主时创建一次 已创建。

    编辑:当您的侦听器停止侦听并且计时器消失时,您可能检查了 Windows 服务仍在运行。查看 ServiceHost 本身是否保留在内存中也很有意义。您还可以在 ServiceHosts 的“Closing”、“Closed”和“Faulted”事件处理程序中添加一些日志记录。

    编辑 2: 如果您的计时器正在消失,那么您应该查看如何分配它。它很可能会被垃圾收集。您必须将其声明为可从活动对象访问的实例字段。让它保持静态以绝对确定。您为DataTimer 执行此操作,但不清楚如何在DataTimer 内声明和分配计时器。请发布一些代码。

    编辑 3: 您不应在操作中创建计时器。如果操作被多次调用会发生什么?老前辈怎么办?我看不到您如何关闭/处置它。您似乎也有两个用于 DataTimer 的构造函数。其中之一是什么都不做。最重要的是,您有单独的计时器列表。这有点令人费解。请隔离问题并在此之后发布新代码。

    【讨论】:

    • 好的,我将向这些偶数处理程序添加日志记录和/或创建一个小定时组件来 ping 我的计时器服务并使其保持活动状态
    • 在添加“保持活动”组件之前实际找出导致此问题的原因可能是个好主意。您将降低您的服务的可靠性并依赖于这个 ping 组件。它也可能消失:)
    • 我明白你的意思。实际上,经过进一步分析,我发现单例记录在内存中。它只是死掉的 System.Timers.Timer 实例变量!我可以看到所有其他实例变量仍然存在。看起来定时器在这里是个问题。
    【解决方案2】:

    我没有特别遇到过这个问题 - 但是,如果您只想在服务运行时运行计时器,为什么不将其设为静态。那么您的实例上下文模式和实例生命周期不会影响您的功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-09
      • 2018-03-10
      • 1970-01-01
      • 1970-01-01
      • 2012-01-13
      • 1970-01-01
      相关资源
      最近更新 更多