這是我第一次嘗試編寫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) –
不客氣。糾正了錯誤。 –