2009-12-23 104 views
0

我在寫一個ASP.NET隊列處理器。用戶將登錄並上傳數據文件到網站,然後單擊開始處理數據文件。將字符串傳遞給.NET Windows服務

我在等待項目到達隊列並處理它們的系統上有一個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

回答一般問題如何可以得到解決(尚不能確定眼前的代碼):

取決於您的要求。從 「容易」 到 「高端」:

  • 文件系統項(與觀察者或輪詢)
  • 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(); 
} 
+0

也可以託管在Windows服務WCF服務,並有ASP.NET應用程序調用該服務。 (關於您的MSMQ建議的更加結構化的變體。) – itowlson 2009-12-23 23:11:21

+0

抱歉關於bNotDoneYet = false丟失;我在代碼的'消毒'中錯過了它。另外,感謝同步採樣。這幾天我沒有做太多同步工作。 – 2009-12-23 23:33:17

+0

@itowlson:好點,錯過了。 – 2009-12-24 08:32:39