2009-12-23 2 views
0

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

У меня есть служба 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

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

зависит от ваших требований. От "легко" до "высокого класса":

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

что касается кода:

Первая мысль, которая пересекает мой ум: Если очередь оказывается пустым о nce вы вырветесь из события таймера, а 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(); 
} 
+0

Может также разместить службу WCF в службе Windows, и иметь ASP.NET приложение вызывает эту услугу. (Более структурированный вариант вашего предложения MSMQ.) – itowlson

+0

Извините, что bNotDoneYet = false отсутствует; Я пропустил это в «дезинфекции» кода. Кроме того, спасибо за образцы синхронизации. В эти дни я не очень много синхронизирую. –

+0

@itowlson: Хороший момент, пропустил это. –

Смежные вопросы