Verarbeitung MSMQ-Nachricht in Windows-Dienst
Ich habe einen windows-Dienst für die Verarbeitung der MSMQ-Nachrichten. Es basiert auf der folgenden Logik
· Es ist ein timer in der windows-Dienst. Alle zehn Minuten wird ausgeführt, die Methode mit dem Namen "ProcessMessages".
· In dieser Methode erstellt zunächst eine Liste der vorhandenen messageIds durch den Aufruf GetAllMessages Methode der Warteschlange.
· Für jede messageId, erhält er die Nachricht (mit ReceiveById) und speichert es in eine Datei
Gibt es eine bessere Möglichkeit das zu erreichen die message-Verarbeitung?
Referenz: http://www.switchonthecode.com/tutorials/creating-a-simple-windows-service-in-csharp
Hinweis: Der folgende code nicht das gewünschte Ergebnis, wenn ich es als Dienst; es ist jedoch kein Fehler in der Ereignisanzeige (ich bin nicht dabei keine explizite Protokollierung). Es war in Ordnung arbeiten, wenn es war eine einfache Konsolen-app. Wie man es richtig? [Nun, es funktioniert, wenn ich änderte die Kon "User", wie gezeigt unten in den Kommentaren]
Meine actaul Voraussetzung ist, um alle Nachrichten zu verarbeiten, die an festen Zeitfenster – sagen wir auf 10 und 11 UHR (nur an jedem Tag). Was ist der beste Ansatz, um dies zu tun?
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);
}
}
}
- Es ist wahrscheinlich ein problem mit Berechtigungen. Versuchen Sie es mit einer der anderen built-in accounts.
- Danke.. Service gearbeitet, wenn ich in den ServiceAccount.Benutzer und gab meinen Benutzernamen und mein Passwort. Was ist die empfohlene Konto hier?
- Ich würde empfehlen, nicht die Verwendung eines dedizierten Benutzer-account in einer Produktions-Umgebung für diese. Das problem wird wahrscheinlich mit dieser KB-Artikel (es geht um Vista, aber das gleiche problem würde wahrscheinlich existieren in 7 und 2008).
- Der link in deiner Frage 404 fyi
Du musst angemeldet sein, um einen Kommentar abzugeben.
Eine schöne alternative zur Verwendung eines Timers ist die Verwendung der
MessageQueue.BeginReceive
Methode und arbeiten in derReceiveCompleted
Veranstaltung. Auf diese Weise kann der code warten, bis es eine Nachricht in der Warteschlange und dann sofort die Nachricht verarbeiten, dann überprüfen Sie für die nächste Nachricht.Einen kurzen stub (eine vollständiges Beispiel im verlinkten MSDN-Artikel.)
Warum nicht abonnieren ReceiveCompleted Veranstaltung? Eine weitere option, wenn beide, sender und Abonnenten ist .Net Projekten Sie arbeiten, verwenden Sie WCF über MSMQ.