将字符串传递给.NET Windows服务

时间:2009-12-23 22:58:41

标签: c# string windows-services parameters

我正在编写一个ASP.NET队列处理器。用户将登录并上传数据文件到站点,然后单击开始处理数据文件。

我在系统上有一个Windows服务,它等待项目到达队列并处理它们。到目前为止一切正常,除了队列中的项目似乎迷路了。我相信静态成员正在失去范围,但我不确定如何解决它。

我考虑过在文件中写入文件,但是状态更新通常会成为性能杀手。

将数据输入和退出服务的最佳方法是什么?

Windows服务如下:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;
using System.Timers;

namespace MyMonitorService
{
    public class MyMonitor : ServiceBase
    {
        #region Members
        private System.Timers.Timer timer = new System.Timers.Timer();
        private static Queue<String> qProjectQueue = new Queue<String>();
        private static Mutex mutexProjectQueue = new Mutex(false);
        private Boolean bNotDoneYet = false;
        #endregion

        #region Properties
        public static String Status { get; private set; }
        #endregion

        #region Construction
        public MyMonitor ()
        {
            this.timer.Interval = 10000; // set for 10 seconds
            this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed);

            Status = String.Empty;
        }
        #endregion

        private void timer_Elapsed (object sender, ElapsedEventArgs e)
        {
            try
            {
                if (!this.bNotDoneYet)
                {
                    this.bNotDoneYet = true;
                    for (;;)
                    {
                        MyMonitor.mutexProjectQueue.WaitOne();
                        if (MyMonitor.qProjectQueue.Count == 0)
                        {
                            EventLog.WriteEntry("MyMonitor", "The queue is empty", EventLogEntryType.Information);
                            break;
                        }
                        String strProject = MyMonitor.qProjectQueue.Dequeue();
                        EventLog.WriteEntry("MyMonitor", String.Format("The project {0} was dequeued", strProject), EventLogEntryType.Information);
                        MyMonitor.mutexProjectQueue.ReleaseMutex();

                        // Do something that updates MyMonitor.Status up to thousands of times per minute
                    }
                }
                this.bNotDoneYet = false;
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry("MyMonitor", ex.Message, EventLogEntryType.Error);
            }
        }

        public static void EnqueueProjects (params String[] astrProjects)
        {
            try
            {
                String strMessage = String.Format("The following projects were added to the queue:\n{0}", String.Join("\n", astrProjects));
                EventLog.WriteEntry("MyMonitor", strMessage, EventLogEntryType.Information);

                if (astrProjects == null)
                    return;

                MyMonitor.mutexProjectQueue.WaitOne();

                foreach (String strProject in astrProjects)
                    MyMonitor.qProjectQueue.Enqueue(strProject);

                MyMonitor.mutexProjectQueue.ReleaseMutex();
            }
            catch (Exception e)
            {
                EventLog.WriteEntry("MyMonitor", e.Message, EventLogEntryType.Error);
            }
        }

        #region Service Start/Stop
        [STAThread]
        public static void Main ()
        {
            ServiceBase.Run(new MyMonitor());
        }

        protected override void OnStart (string[] args)
        {
            try
            {
                EventLog.WriteEntry("MyMonitor", "MyMonitor Service Started", EventLogEntryType.Information);
                this.timer.Enabled = true;
            }
            catch (Exception e)
            {
                EventLog.WriteEntry("MyMonitor", e.Message, EventLogEntryType.Error);
            }
        }

        protected override void OnStop ()
        {
            try
            {
                EventLog.WriteEntry("MyMonitor", "MyMonitor Service Stopped", EventLogEntryType.Information);
                this.timer.Enabled = false;
            }
            catch (Exception e)
            {
                EventLog.WriteEntry("MyMonitor", e.Message, EventLogEntryType.Error);
            }
        }
        #endregion
    }
}

1 个答案:

答案 0 :(得分:1)

回答一般性问题如何解决这个问题(仍然不确定手头的代码):

取决于您的要求。从“简单”到“高端”:

  • 文件系统条目(带观察者或投票)
  • Windows消息,SendMessage / PostMessage
  • 共享数据库层
  • 消息队列(例如MS MQ)

关于您的代码:

首先想到的是我的想法:如果队列碰巧是空的,一旦你打破了计时器事件而且bNotDoneYet永远不会重置为假 - &gt;新的参赛作品不会被考虑?

此外,您的生产者/消费者模式似乎对我不利。我习惯了轻量级(简化):

制片:

lock (_syncRoot) {
  _queue.Enqueue(obj);
  if (_queue.Count == 1) Monitor.Pulse(_syncRoot);
}

消费者:

lock (_syncRoot) {
  while (_queue.Count < 1) {
    try {
      Monitor.Wait(_syncRoot);
    } catch (ThreadInterruptedException) {}
  }
  var obj = _queue.Dequeue();
}