2012-03-28 28 views
7

MSMQ iletilerini işlemek için bir Windows hizmetim var. Aşağıdaki mantığa dayanır:Windows Hizmetinde MSMQ İletisi İşleme

· Windows servisinde bir zamanlayıcı var. Her on dakikada bir “ProcessMessages” isimli yöntemi uygulayacaktır.

· Bu yöntemin içinde, önce sıranın GetAllMessages yöntemini çağırarak varolan mesajların bir listesini oluşturur. Her MessageID için

·, bir dosyanın

mesajı işleme ulaşmak için daha iyi bir yolu var mı içine mesajı (ReceiveById kullanarak) ve depolar aldığı?

Referans: http://www.switchonthecode.com/tutorials/creating-a-simple-windows-service-in-csharp

Not: Ben bir hizmet olarak bunu yaptığında Aşağıdaki kod istenilen sonucu vermez; Ancak olay görüntüleyicide bir hata yok (açık bir kayıt yapmıyorum). Basit bir konsol uygulaması olduğunda iyi çalışıyordu. Nasıl düzeltilir? [Şu andaki hesapta "Kullanıcı" olarak "Kullanıcı" olarak shuayı değiştirdiğimde çalışıyorum]

Tüm mesajlarım, tüm mesajları belirli zaman dilimlerinde işlemek - sadece 10:00 ve 11:00 (her gün)). Bunu yapmanın en iyi yolu nedir?

namespace ConsoleSwitchApp 
{ 
    class Program : ServiceBase 
    { 
     private static Timer scheduleTimer = null; 
     static MessageQueue helpRequestQueue = null; 
     static System.Messaging.XmlMessageFormatter stringFormatter = null; 

     static void Main(string[] args) 
     { 
      ServiceBase.Run(new Program()); 
     } 

     public Program() 
     { 
      this.ServiceName = "LijosService6"; 

      //Queue initialize 
      helpRequestQueue = new MessageQueue(@".\Private$\MyPrivateQueue", false); 
      stringFormatter = new System.Messaging.XmlMessageFormatter(new string[] { "System.String" }); 

      //Set Message Filters 
      MessagePropertyFilter filter = new MessagePropertyFilter(); 
      filter.ClearAll(); 
      filter.Body = true; 
      filter.Label = true; 
      filter.Priority = true; 
      filter.Id = true; 
      helpRequestQueue.MessageReadPropertyFilter = filter; 

      //Start a timer 
      scheduleTimer = new Timer(); 
      scheduleTimer.Enabled = true; 
      scheduleTimer.Interval = 120000;//2 mins 
      scheduleTimer.AutoReset = true; 
      scheduleTimer.Start(); 
      scheduleTimer.Elapsed += new ElapsedEventHandler(scheduleTimer_Elapsed); 
     } 

     protected static void scheduleTimer_Elapsed(object sender, ElapsedEventArgs e) 
     { 
      ProcessMessages(); 
     } 

     private static void ProcessMessages() 
     { 
      string messageString = "1"; 

      //Message Processing 
      List<string> messageIdList = GetAllMessageId(); 
      foreach (string messageId in messageIdList) 
      { 
       System.Messaging.Message messages = helpRequestQueue.ReceiveById(messageId); 
       //Store the message into database 

       messages.Formatter = stringFormatter; 
       string messageBody = System.Convert.ToString(messages.Body); 

       if (String.IsNullOrEmpty(messageString)) 
       { 
        messageString = messageBody; 
       } 
       else 
       { 
        messageString = messageString + "___________" + messageBody; 
       } 
      } 

      //Write File 
      string lines = DateTime.Now.ToString(); 
      lines = lines.Replace("/", "-"); 
      lines = lines.Replace(":", "_"); 
      System.IO.StreamWriter file = new System.IO.StreamWriter("c:\\test" + lines + ".txt"); 
      file.WriteLine(messageString); 
      file.Close(); 
     } 

     private static List<string> GetAllMessageId() 
     { 
      List<string> messageIdList = new List<string>(); 

      DataTable messageTable = new DataTable(); 
      messageTable.Columns.Add("Label"); 
      messageTable.Columns.Add("Body"); 

      //Get All Messages 
      System.Messaging.Message[] messages = helpRequestQueue.GetAllMessages(); 
      for (int index = 0; index < messages.Length; index++) 
      { 
       string messageId = (System.Convert.ToString(messages[index].Id)); 
       messageIdList.Add(messageId); 

       messages[index].Formatter = stringFormatter; 
       messageTable.Rows.Add(new string[] { messages[index].Label, messages[index].Body.ToString() }); 
      } 

      return messageIdList; 
     } 


     protected override void OnStart(string[] args) 
     { 
      base.OnStart(args); 
     } 

     protected override void OnStop() 
     { 
      base.OnStop(); 
     } 
    } 
} 

namespace ConsoleSwitchApp 
{ 
    [RunInstaller(true)] 
    public class MyWindowsServiceInstaller : Installer 
    { 
     public MyWindowsServiceInstaller() 
     { 
      var processInstaller = new ServiceProcessInstaller(); 
      var serviceInstaller = new ServiceInstaller(); 

      //set the privileges 
      processInstaller.Account = ServiceAccount.LocalSystem; 
      serviceInstaller.DisplayName = "LijosService6"; 
      serviceInstaller.StartType = ServiceStartMode.Manual; 

      //must be the same as what was set in Program's constructor 

      serviceInstaller.ServiceName = "LijosService6"; 

      this.Installers.Add(processInstaller); 
      this.Installers.Add(serviceInstaller); 
     } 
    } 
} 
+1

Muhtemelen bir izin sorunu var. Diğer yerleşik hesaplardan birini kullanmayı deneyin. –

+0

@ M.Babcock Teşekkürler .. ServiceAccount.User kullandım ve kullanıcı adımı ve şifremi verdiğimde servis çalıştı. Önerilen hesap nedir? – Lijo

+1

Bunun için bir üretim ortamında özel bir kullanıcı hesabı kullanarak ** tavsiye etmem. Sorun büyük olasılıkla [bu KB makalesi] ile ilişkilidir (http://support.microsoft.com/kb/952569) (Vista ile ilgili olmakla birlikte aynı problem 7 ve 2008'de de olasıdır). –

cevap

14

bir zamanlayıcı kullanarak için güzel bir alternatif MessageQueue.BeginReceive yöntemi kullanmak ve ReceiveCompleted olay çalışmalarını yapmaktır. Bu şekilde kodunuz sıradaki bir mesaj olana kadar bekleyecektir ve ardından mesajı hemen işleyecek, ardından bir sonraki mesajı kontrol edecektir.

Kısa saplama (bağlı MSDN makalesinde tam bir örnek.)

private void Start() 
{ 
    MessageQueue myQueue = new MessageQueue(".\\myQueue"); 

    myQueue.ReceiveCompleted += 
     new ReceiveCompletedEventHandler(MyReceiveCompleted); 

    myQueue.BeginReceive(); 
} 

private static void MyReceiveCompleted(Object source, 
    ReceiveCompletedEventArgs asyncResult) 
{ 
    try 
    { 
     MessageQueue mq = (MessageQueue)source; 
     Message m = mq.EndReceive(asyncResult.AsyncResult); 

     // TODO: Process the m message here 

     // Restart the asynchronous receive operation. 
     mq.BeginReceive(); 
    } 
    catch(MessageQueueException) 
    { 
     // Handle sources of MessageQueueException. 
    } 

    return; 
} 
+0

Benim gereksinimim, tüm mesajları belirli zaman aralıklarında işlemek - yani sadece 10:00 ve 11:00 (her gün). Bunu yapmanın en iyi yolu nedir? – Lijo

+6

Bir Konsol Uygulaması çalıştırmak için Windows Görev Zamanlayıcısı'nı kullanın. – Tommassiov

2

Neden ReceiveCompleted olaya abone olmak değil? Bir başka seçenek, hem gönderen hem de abone çalışıyorsanız .Net projeleri üzerinde çalışıyorsanız, WCF over MSMQ kullanın.

+0

Gereksinim, tüm mesajları belirli zaman aralıklarında işlemek - sadece 10:00 ve 11:00 (her gün). Bunu yapmanın en iyi yolu nedir? – Lijo

+1

MSMQ'ya Anonim etki alanı hesabına erişim vermelisiniz – paramosh