【问题标题】:How to initialize singleton class in Windows Service Hosted WCF Service on startup如何在启动时在 Windows 服务托管 WCF 服务中初始化单例类
【发布时间】:2016-06-05 22:45:33
【问题描述】:

我编写了 Windows 服务托管 wcf 服务。 服务行为为:[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]

我从数据库中读取了一些数据并在启动时创建了一些共享类。即使没有请求,也有一些计时器应该工作。初始化也需要一些时间。

所有这些初始化都发生在另一个 dll 中的单例类中。我尝试描述here 的不同signleton 类初始化。

但是直到第一个请求到达时单例类才被初始化。计时器、从数据库加载的对象……等等。它们都在这个单例类中。在第一个请求到达后一切正常。即使未初始化类,服务似乎也在服务窗口上工作。

在请求到达之前的调试器中,dll 甚至没有加载。 如何在启动时初始化这个单例类?

这是服务行为问题还是我应该更改 Windows 服务安装程序?

编辑: 重新格式化问题。

【问题讨论】:

标签: c# wcf windows-services


【解决方案1】:

您可以在 OnStart windows 服务事件上启动 WCF 服务并在 OnStop windows 事件上停止它。您可以在 Windows 事件日志中添加一些诊断信息,以查看是否有任何异常并检查服务是否已启动等。

using System;
using System.ServiceModel;
using System.ServiceProcess;
using System.Diagnostics;
using System.Configuration;
using System.Timers;
using System.Collections.Generic;

namespace MyWCF
{
    public partial class WcfOverHttpService : ServiceBase
    {
        private ServiceHost m_host;

        public WcfOverHttpService()
        {
            System.Diagnostics.EventLog.WriteEntry(" WCF Interface", " Constructor called.", EventLogEntryType.Information);
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            try
            {
                System.Diagnostics.EventLog.WriteEntry(" WCF Interface", "On Start called.", EventLogEntryType.Information);
                StartWcfService();
            }
            catch (Exception ex)
            {
                System.Diagnostics.EventLog.WriteEntry(" WCF Interface","On Start failed :"+ex.ToString(), EventLogEntryType.Error);
                throw ex;
            }
        }

         private void StartWcfService()
        {
            try
            {
                System.Diagnostics.EventLog.WriteEntry(" WCF Interface", "Start Wcf Service.", EventLogEntryType.Information);
                m_host = new ServiceHost(typeof(MyWCFService));
                m_host.Open();
                System.Diagnostics.EventLog.WriteEntry(" WCF Interface", "WCF Service HostOpen.", EventLogEntryType.Information);
            }
            catch (Exception ex)
            {
                System.Diagnostics.EventLog.WriteEntry(" WCF Interface", "Start WCF Service failed :" + ex.ToString(), EventLogEntryType.Error);
                throw ex;
            }
        }

        protected override void OnStop()
        {
            try
            {
                System.Diagnostics.EventLog.WriteEntry(" WCF Interface", "On Stop called.", EventLogEntryType.Information);
                if (m_host != null)
                {
                    System.Diagnostics.EventLog.WriteEntry(" WCF Interface", "Stop WCF Service.", EventLogEntryType.Information);
                    m_host.Close();
                    m_host = null;
                }

            }
            catch(Exception ex)
            {
                System.Diagnostics.EventLog.WriteEntry(" WCF Interface", "On Stop failed :" + ex.ToString(), EventLogEntryType.Error);
                throw ex;
                //handle exception
            }
        }

    }
}

这就是实现计时器逻辑的方式。

using System;
using System.ServiceModel;
using System.ServiceProcess;
using System.Diagnostics;
using System.Configuration;
using System.Timers;
using System.Collections.Generic;

namespace MyAppNameSpace
{
    public partial class MyWCFService : ServiceBase
    {
        private ServiceHost m_host;
        System.Timers.Timer MyProductionTimer = null;
        bool _MyProductionRunOnce = false;

        //// Put this values in Config 
        private string MyProductionSchedule = "DAILY";
        private string MyProductionToRun = "MANY";
        private string MyProductionStartTime = "10:00 PM";
        private int MyProductionPollInterval = 60000;


        public MyWCFService()
        {
            System.Diagnostics.EventLog.WriteEntry("My  WCF Interface Constructor", " Constructor called.", EventLogEntryType.Information);

            InitializeComponent();
            //Create Timer Object and register tick event
             this.MyProductionTimer = new System.Timers.Timer(MyProductionPollInterval);
             this.MyProductionTimer.Elapsed += new ElapsedEventHandler(this.MyProductionTimer_Tick);


        }

        protected override void OnStart(string[] args)
        {
            try
            {
                System.Diagnostics.EventLog.WriteEntry("My  WCF Interface Start", "On Start called.", EventLogEntryType.Information);

                StartWcfService();

                 // Setup timer and start it 
                this.MyProductionTimer.Interval = MyProductionPollInterval;
                this.MyProductionTimer.Enabled = true;
                this.MyProductionTimer.Start();
                System.Diagnostics.EventLog.WriteEntry("My  MyProduction Timer Start", "MyProduction Timer Start At :" + DateTime.Now.ToString(), EventLogEntryType.Information);

            }
            catch (Exception ex)
            {
                System.Diagnostics.EventLog.WriteEntry("My  WCF Interface Start Error","On Start failed :"+ex.ToString(), EventLogEntryType.Error);

                throw ex;
            }
        }

        protected override void OnStop()
        {
            try
            {
                System.Diagnostics.EventLog.WriteEntry("My  WCF Interface Stop", "On Stop called.", EventLogEntryType.Information);

                //Stop the timer
                this.MyProductionTimer.Stop();
                System.Diagnostics.EventLog.WriteEntry("My  MyProduction Timer Stop", "MyProduction Timer Stopped At :" + DateTime.Now.ToString(), EventLogEntryType.Information);

                if (m_host != null)
                {
                    System.Diagnostics.EventLog.WriteEntry("My  WCF Interface Stopped", "Stop Wc fService.", EventLogEntryType.Information);

                    m_host.Close();
                    m_host = null;
                }


            }
            catch(Exception ex)
            {
                System.Diagnostics.EventLog.WriteEntry("My  WCF Interface Stop Error", "On Stop failed :" + ex.ToString(), EventLogEntryType.Error);

                throw ex;
                //handle exception
            }
        }

        //Timer Tick Event
        private void MyProductionTimer_Tick(object sender, EventArgs e)
        {
            this.MyProductionTimer.Stop();
            this.MyProductionTimer.Interval = MyProductionPollInterval;
            bool runFlag = false;

            try
            {

                // Find out if it is time to run logic based on schedule
                string dw = DateTime.Now.DayOfWeek.ToString();

                if ((MyProductionSchedule.ToUpper() == "DAILY" && MyProductionToRun.ToUpper() == "ONCE") ||
                    (MyProductionSchedule.ToUpper() == dw.ToUpper() && MyProductionToRun.ToUpper() == "ONCE"))
                {
                    if (checkPolTime(MyProductionStartTime))
                        _MyProductionRunOnce = true;

                    if (_MyProductionRunOnce)
                    {
                        _MyProductionRunOnce = false;
                        runFlag = true;
                    }
                }
                else if ((MyProductionSchedule.ToUpper() == "DAILY" && MyProductionToRun.ToUpper() == "MANY") ||
                        (MyProductionSchedule.ToUpper() == dw.ToUpper() && MyProductionToRun.ToUpper() == "MANY"))
                {
                    if (!_MyProductionRunOnce)
                    {
                        if (checkPolTime(MyProductionStartTime))
                            _MyProductionRunOnce = true;
                    }

                    if (_MyProductionRunOnce)
                        runFlag = true;
                }
                else
                {
                    _MyProductionRunOnce = false;
                }

                if (runFlag)
                {
                    // Your Timer Business Logic  goes here
                }
            }
            catch (Exception exc)
            {
                System.Diagnostics.EventLog.WriteEntry(" MyProduction Timer Error",
                    exc.Message, EventLogEntryType.Error);
            }
            finally
            {
                this.MyProductionTimer.Start();//To restart the processing of production
            }
        }
        private void StartWcfService()
        {
            try
            {
                System.Diagnostics.EventLog.WriteEntry("My  WCF Interface Create Host", "Start Wcf Service.", EventLogEntryType.Information);
                m_host = new ServiceHost(typeof(WcfService));
                m_host.Open();
                System.Diagnostics.EventLog.WriteEntry("My  WCF Interface Host Opened", "WCF Service HostOpen.", EventLogEntryType.Information);
            }
            catch (Exception ex)
            {
                System.Diagnostics.EventLog.WriteEntry("My  WCF Interface Exception", "Start WCF Service failed :" + ex.ToString(), EventLogEntryType.Error);

                throw ex;
            }
        }

        // Utility to check if it is time to run the timer logic
        public static bool checkPolTime(string ProdStartTime)
        {
            DateTime t1 = DateTime.Now;
            DateTime t2 = Convert.ToDateTime(ProdStartTime);
            int i = DateTime.Compare(t1, t2);
            if (i >= 0)
            {
                return true;
            }
            else
            {
                return false;
           }
        }


    }
}

【讨论】:

  • 我想我无法正确解释问题。我编辑了这个问题。这不是启动问题。服务启动就好了。但在请求到达之前,一些静态构造函数根本没有运行。
  • @fyo 将您的计时器放在 Windows 服务而不是 WCF 服务中。通过这种方式,您可以保证您的计时器将触发,并且在您的计时器生成的第一个请求时将创建所需的 WCF 服务实例。
  • 如果我误解了,请纠正我。在任何请求到达之前,无法初始化此单例实例。 Soi 必须更改 Windows 服务才能发送第一个请求。
  • 还有一件事,我该怎么做?
  • @fyo 我已经修改了显示如何调用计时器逻辑的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-16
  • 2011-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多