我正在使用从私有 MSMQ 队列读取消息的旧 Windows 服务处理它们(做一些数据库工作,发送一些电子邮件),然后等待下一条消息(PeekCompleted)
该服务存在问题 - 每当 Windows 更新需要重新启动服务器时(几乎总是如此),该服务会以“已启动”状态重新启动,但必须手动重新启动,否则消息只会堆积在队列中。
我的第一个倾向是认为 OnStart 处理程序中的某些内容在服务器重新启动时没有受到影响,我正在尝试整理日志(另一个故事)但 Windows 服务和线程不是我的正常域所以我希望有人能指出我正确的方向......
下面是 OnStart Handler 和消息处理函数,去掉了无关紧要的东西。
问题:在 OnStart 中,MessageRecieved 函数附加到 PeekCompleted 事件。我假设 OnStart 在服务器恢复时触发,因此必须附加处理程序,但我不清楚(a)在重新启动时已经在队列中或(b)在重新启动期间到达的消息是否会真正触发事件 ?
如果应该还有其他我应该寻找的东西吗?
欢迎任何建议!
protected override void OnStart(string[] args)
{
try
{
_inProcess = false;
_queueMessage = null;
_stopping = false;
_queue = ReadyQueue(_queueName);
if (_queue == null)
{
throw new Exception(string.Format("'ReadyFormQueue({0})' returned null", _queueName));
}
_queue.PeekCompleted += new PeekCompletedEventHandler(MessageReceived);
_queue.Formatter = new BinaryMessageFormatter();
_queue.BeginPeek();
}
catch (Exception exception)
{
//do cleanup and other recovery stuff
}
}
private void MessageReceived(object sender, PeekCompletedEventArgs e)
{
_currentMessage = null;
_inProcess = false;
try
{
_queueMessage = _queue.EndPeek(e.AsyncResult);
_queueMessage.Formatter = new BinaryMessageFormatter();
_currentMessage = (MyMessageType)_queueMessage.Body;
_queue.ReceiveById(_queueMessage.Id);
_inProcess = true;
_helper = new MessageHelper();
_currentMessage = _helper.Process(_currentMessage); //sets global _inProcess flag
if (_inProcess)
{
Thread.Sleep((int)(_retryWaitTime * 0x3e8));
SendFormMessageToQueue(FailedQueueName, _currentMessage);
}
else
{
_queue.BeginPeek();
}
}
catch (Exception exception)
{
_inProcess = false;
//do other recovery stuff
if (_currentMessage != null)
{
ReadyFormQueue(_poisonQueueName);
SendFormMessageToQueue(_poisonQueueName, _currentMessage);
}
}
}