这是我第一次尝试编写Windows服务。多线程Windows服务处理Windows Message Queue
此窗口服务必须处理2个窗口消息队列。
每个消息队列应该有自己的线程,但我似乎无法得到架构就地。
我跟着这个Windows Service to run constantly,它允许我创建一个线程,我正在处理一个队列。
所以这是我的服务类:
protected override void OnStart(string[] args)
{
_thread = new Thread(WorkerThreadFunc) { Name = "Address Calculator Thread", IsBackground = true };
_thread.Start();
}
private void WorkerThreadFunc()
{
_addressCalculator = new GACAddressCalculator();
while (!_shutdownEvent.WaitOne(0))
{
_addressCalculator.StartAddressCalculation();
}
}
protected override void OnStop()
{
_shutdownEvent.Set();
if (!_thread.Join(5000))
{ // give the thread 5 seconds to stop
_thread.Abort();
}
}
在我GACAddressCalculator.StartAddressCalculation()
我创建一个队列处理器的对象,看起来像这样:
public void StartAddressCalculation()
{
try
{
var googleQueue = new GISGoogleQueue("VehMonLogGISGoogle", 1, _gacLogger, 1);
googleQueue.ProccessMessageQueue();
}
catch (Exception ex)
{
}
}
这是GISGoogleQueue
:
public class GISGoogleQueue : BaseMessageQueue
{
public GISGoogleQueue(string queueName, int threadCount, GACLogger logger, int messagesPerThread)
: base(queueName, threadCount, logger, messagesPerThread)
{
}
public override void ProccessMessageQueue()
{
if (!MessageQueue.Exists(base.QueueName))
{
_logger.LogMessage(MessageType.Information, string.Format("Queue '{0}' doesn't exist", this.QueueName));
return;
}
var messageQueue = new MessageQueue(QueueName);
var myVehMonLog = new VehMonLog();
var o = new Object();
var arrTypes = new Type[2];
arrTypes[0] = myVehMonLog.GetType();
arrTypes[1] = o.GetType();
messageQueue.Formatter = new XmlMessageFormatter(arrTypes);
using (var pool = new Pool(ThreadCount))
{
// Infinite loop to process all messages in Queue
for (; ;)
{
for (var i = 0; i < MessagesPerThread; i++)
{
try
{
while (pool.TaskCount() >= MessagesPerThread) ; // Stop execution until Tasks in pool have been executed
var message = messageQueue.Receive(new TimeSpan(0, 0, 5, 0)); // TimeOut for message reading from Queue, set to 5 minutes, Will throw exception after 5 mins
if (message != null) // Check if message is not Null
{
var monLog = (VehMonLog)message.Body;
pool.QueueTask(() => ProcessMessageFromQueue(monLog)); // Add to Tasks list in Pool
}
}
catch (Exception ex)
{
}
}
}
}
}
}
现在这适用于1消息队列,但如果我想处理另一个消息队列它不会发生,因为我在ProccessMessageQueue
方法中有一个无限循环。
我想在一个单独的线程中执行每个队列。
我认为我在WorkerThreadFunc()
中犯了一个错误,我必须以某种方式从那里启动两个线程或在OnStart()
。
此外,如果您有任何提示如何改善此服务将是伟大的。
通过我使用的池类从这个答案https://stackoverflow.com/a/436552/1910735线程池里面ProccessMessageQueue
感谢您的好评。我认为你在RunMessageQueueFunc()中有一个错字:while(!_shutdownEvent.Wait(0))我认为它应该是:!_shutdownEvent.WaitOne(0) –
不客气。纠正了错误。 –