Dav*_*vid 7 .net c# wcf windows-services msmq
我有一个使用MSMQ进行异步处理的应用程序.
我使用WCF将消息放入队列,并使用WCF MSMQ监听器(Windows服务)来接收消息并处理它们.
我的问题是保持稳定.处理(例如)队列服务器(这是一个单独的盒子)的正确方法是什么?前几天发生这种情况并且服务只是坐在那里 - 没有抛出任何异常,它只是停止接收消息.我希望它在队列服务器关闭时抛出异常,然后重新尝试连接到它,直到它能够.
我还注意到在服务上执行"停止"通常会导致它在最终停止之前挂起很长一段时间.
任何代码建议或批评都是受欢迎的.显然我首先为谷歌做了这个,但是大多数例子向我展示了我已经拥有的东西,并且我想让我的系统比这更强大.
目前我有这个:
(注意:IMyExampleServiceContract是我的WCF服务合同,QueueHandler是实现它的)
namespace xyz.MyExample.MSMQListener
{
    /// <summary>
    /// The class that handles starting and stopping of the WCF MSMQ Listener windows service.
    /// It will respond to start and stop commands from within the windows services administration snap-in
    /// It creates a WCF NetMsmqBinding that watches a particular queue for messaages defined by a contract
    /// in the ServiceContracts project.
    /// </summary>
    public partial class MsmqListenerService : ServiceBase
    {
        /// <summary>
        /// The WCF service host
        /// </summary>
        private ServiceHost _serviceHost;
        /// <summary>
        /// Defines the maximum size for a WCF message
        /// </summary>
        private const long MaxMessageSize = 1024 * 1024 * 1024; // 1 gb
        /// <summary>
        /// Defines the maximum size for a WCF array
        /// </summary>
        private const int MaxArraySize = 1024 * 1024 * 1024; // 1 gb
        /// <summary>
        /// The queue name
        /// </summary>
        private readonly string _queueName;
        /// <summary>
        /// The queue server
        /// </summary>
        private readonly string _queueServer;
        /// <summary>
        /// Initializes a new instance of the <see cref="MsmqListenerService"/> class.
        /// </summary>
        public MsmqListenerService()
        {
            InitializeComponent();
            using (ConfigManager config = new ConfigManager())
            {
                _queueName = config.GetAppSetting("QueueName");
                _queueServer = config.GetAppSetting("QueueServer");
            }
        }
        /// <summary>
        /// When implemented in a derived class, executes when a Start command is sent to the service by the Service Control Manager (SCM) or when the operating system starts (for a service that starts automatically). Specifies actions to take when the service starts.
        /// <para>
        /// The logic in this method creates a WCF service host (i.e. something that listens for messages) using the <see cref="IMyExampleServiceContract"/> contract.
        /// The WCF end point is a NetMSMQBinding to the MyExample MSMQ server/queue.
        /// It sets up this end point and provides a class to handle the messages received on it.
        /// The NetMSMQBinding is a Microsoft WCF binding that handles serialisation of data to MSMQ. It is a ms proprietary format and means that the message on the queue
        /// can only be read by a WCF service with the correct contract information.
        /// </para>
        /// </summary>
        /// <param name="args">Data passed by the start command.</param>
        protected override void OnStart(string[] args)
        {
            try
            {
                Logger.Write("MyExample MSMQ listener service started.", StandardCategories.Information);
                Uri serviceUri = new Uri("net.msmq://" + QueueServer + QueueName);
                NetMsmqBinding serviceBinding = new NetMsmqBinding();
                serviceBinding.Security.Transport.MsmqAuthenticationMode = MsmqAuthenticationMode.None;
                serviceBinding.Security.Transport.MsmqProtectionLevel = System.Net.Security.ProtectionLevel.None;
                serviceBinding.MaxReceivedMessageSize = MaxMessageSize;
                serviceBinding.ReaderQuotas.MaxArrayLength = MaxArraySize;
                //QueueHandler implements IMyExampleServiceContract
                _serviceHost = new ServiceHost(typeof(QueueHandler));
                _serviceHost.AddServiceEndpoint(typeof(IMyExampleServiceContract), serviceBinding, serviceUri);
                _serviceHost.Open();
                Logger.Write("MyExample MSMQ listener service completed OnStart method.", StandardCategories.Information);
            }
            catch (Exception ex)
            {
                ExceptionReporting.ReportException(ex, "DefaultExceptionPolicy");
                throw;
            }
        }
        /// <summary>
        /// Gets the name of the queue to send to. 
        /// This is retrieved from the application settings under QueueName
        /// </summary>
        private string QueueName
        {
            get { return _queueName; }
        }
        /// <summary>
        /// Gets the name of the queue server to send to. 
        /// This is retrieved from the application settings under QueueServer
        /// </summary>
        private string QueueServer
        {
            get { return _queueServer; }
        }
        /// <summary>
        /// When implemented in a derived class, executes when a Stop command is sent to the service by the Service Control Manager (SCM). Specifies actions to take when a service stops running.
        /// </summary>
        protected override void OnStop()
        {
            if (_serviceHost != null)
            {
                _serviceHost.Close();
                _serviceHost = null;
            }
        }
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        public static void Main()
        {
            //Code will have to be compiled in release mode to be installed as a windows service
            #if (!DEBUG)
                try
                {
                    Logger.Write("Attempting to start queue listener service.", StandardCategories.Information);
                    ServiceBase[] ServicesToRun;
                    ServicesToRun = new ServiceBase[]
                            {
                            new MsmqListenerService()
                            };
                    ServiceBase.Run(ServicesToRun);
                    Logger.Write("Finished ServiceBase.Run of queue listener service.", StandardCategories.Information);
                }
                catch (Exception e)
                {
                    ExceptionReporting.ReportException(e, "DefaultExceptionPolicy");
                    throw;
                }
            #else
                //This allows us to run from within visual studio
                MsmqListenerService service = new MsmqListenerService();
                service.OnStart(null);
                System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
            #endif
        }
    }
}