2009-12-23 3 views
0

ASP.NET 큐 프로세서를 작성하고 있습니다. 사용자는 로그인하고 데이터 파일을 사이트에 업로드 한 다음을 클릭하여 데이터 파일 처리를 시작합니다.문자열을 .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

을이 해결 될 수있는 방법을 일반 질문 (손에있는 코드에 대한 아직 확실하지) 응답 :

사용자의 요구 사항에 따라 다름을 다음과 같이

윈도우 서비스입니다. 에서 "쉬운" "하이 엔드"에 :

  • Windows 메시지, sendMessage 첨부/PostMessage를
  • 공유 데이터베이스 계층
  • 메시지 큐 (MS MQ (감시자 또는 폴링와)

    • 파일 시스템 항목 코드에 대해서는 예)

    에 대한 :

    내 마음을 교차

    먼저 생각 : 큐가 비어 O로 발생하는 경우 타이머 이벤트에서 빠져 나와 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

    +0

    bNotDoneYet = false가 누락 된 점에 대해 사과드립니다. 나는 코드의 'sanitization'에서 그것을 놓쳤다. 또한 동기화 샘플을 보내 주셔서 감사합니다. 요즘에는 동기화를 많이하지 않습니다. –

    +0

    @itowlson : 좋은 지적입니다. –

    관련 문제