Передача строк в .NET Windows Service - PullRequest
0 голосов
/ 24 декабря 2009

Я пишу обработчик очереди ASP.NET.Пользователи будут входить в систему и загружать файлы данных на сайт, а затем нажимать, чтобы начать обработку файлов данных.

В моей системе установлена ​​служба Windows, которая ожидает поступления элементов в очередь и обрабатывает их.Пока все работает, кроме элементов в очереди, кажется, теряются.Я полагаю, что статические члены теряют область видимости, но я не уверен, как это исправить.

Я думал о записи вещей в / из файлов, но Состояние обновляется так часто, что это может привести к снижению производительности.1005 *

Каков наилучший способ ввода и вывода данных из службы?

Служба 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 Ответ

1 голос
/ 24 декабря 2009

Отвечая на общий вопрос, как это можно решить (все еще не уверены насчет кода):

Зависит от ваших требований. От «простого» до «высокого класса»:

  • Записи файловой системы (с наблюдателем или опросом)
  • Сообщения Windows, SendMessage / PostMessage
  • Уровень общей базы данных
  • очереди сообщений (например, MS MQ)

Относительно вашего кода:

Первая мысль, которая приходит мне в голову: если очередь окажется пустой, как только вы выйдете из события таймера, и bNotDoneYet никогда не будет сброшен в false -> Новые записи не будут рассматриваться?

Кроме того, мне кажется, что ваша модель "производитель / потребитель" мне не подходит. Я привык к легкому (и упрощенному):

Производитель:

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();
}
...