我有一个Windows 服务可以进行一些图像转换。它可以在重命名任何文件(在特定文件夹中)时触发(即重命名文件观察者)。工作得很好,直到我在该文件夹中转储(和重命名)大量图像。 CPU红线等。
所以,我打算将我的代码更改为使用 MSMQ 排队所有需要转换的文件。精细。每次重命名文件并触发文件监视器时,我都会向队列中添加一条新消息。 KEWL。
问题是这个 - > 如何从队列中一次抓取一条消息?
我是否需要制作一个定时器对象,每隔xxx秒轮询一次队列?或者有没有办法不断窥视队列中的第一个项目。一旦消息存在,提取它,处理它,然后继续(这意味着,继续偷看直到世界爆炸)。
我想知道我是否只需要在Receive方法周围放置一个while循环。 Pseduo代码如下(在编辑#2中)......
任何人都有这方面的经验并有一些建议吗?
非常感谢!
如果可以使用WCF,有人可以提供一些示例代码等吗?
这是我想到的一些伪代码......
// Windows service start method.
protected override void OnStart(string[] args)
{
// some initialisation stuf...
// Start polling the queue.
StartPollingMSMQ();
// ....
}
private static void StartPollingMSMQ()
{
// NOTE: This code should check if the queue exists, instead of just assuming it does.
// Left out for berevity.
MessageQueue messageQueue = new MessageQueue(".\\Foo");
while (true)
{
// This blocks/hangs here until a message is received.
Message message = messageQueue.Receive(new TimeSpan(0, 0, 1));
// Woot! we have something.. now process it...
DoStuffWithMessage(message);
// Now repeat for eva and eva and boomski...
}
}
答案 0 :(得分:26)
如果使用本地队列,则不需要WCF。
这是我的示例服务(来自Windows服务项目的服务)的看法:
using System.Messaging;
public partial class MQProcessTest1 : ServiceBase
{
//a name of the queue
private const string MqName = @".\Private$\test1";
//define static local private queue
private static MessageQueue _mq;
//lazy local property through which we access queue (it initializes queue when needed)
private static MessageQueue mq
{
get
{
if (_mq == null)
{
if (!MessageQueue.Exists(MqName))
MessageQueue.Create(MqName);
_mq = new MessageQueue(MqName, QueueAccessMode.ReceiveAndAdmin);
_mq.Formatter = new BinaryMessageFormatter();
}
return _mq;
}
}
//constructor
public MQProcessTest1()
{
InitializeComponent();
//event to process received message
mq.ReceiveCompleted += new ReceiveCompletedEventHandler(mq_ReceiveCompleted);
}
//method to process message
private void mq_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
{
//queue that have received a message
MessageQueue cmq = (MessageQueue)sender;
try
{
//a message we have received (it is already removed from queue)
Message msg = cmq.EndReceive(e.AsyncResult);
//here you can process a message
}
catch
{
}
//refresh queue just in case any changes occurred (optional)
cmq.Refresh();
//tell MessageQueue to receive next message when it arrives
cmq.BeginReceive();
}
protected override void OnStart(string[] args)
{
//let start receive a message (when arrives)
if (mq != null)
mq.BeginReceive();
//you can do any additional logic if mq == null
}
protected override void OnStop()
{
//close MessageQueue on service stop
if (mq != null)
mq.Close();
return;
}
}
答案 1 :(得分:1)
我的印象是MSMQ的构建与IBM的MQ产品兼容。如果 ,则可以使用超时调用MQGET,而不必担心轮询。
只需从队列中获取一条消息(例如)。如果那里有一个,处理它。然后,如果需要,可以退出服务,或者等待返回MQGET。
这意味着您的服务不会不必要地占用CPU时间,但如果发出信号,它仍然可以及时退出。
一般来说,你会有类似的东西:
Set up all queue stuff.
while true:
Read from queue with 10-second timeout.
If message was read:
Process message
If signaled to exit:
break
Tear down queue stuff.
Exit.
答案 2 :(得分:1)
在ViktorJ示例中使用事件args来获取您的消息而不是发送者到新的MessageQueue,这肯定会更有效吗?然后使用静态字段mq调用mq.BeginReceive,否则调用内存
答案 3 :(得分:0)
听起来你需要调查WCF。
Queues in Windows Communication Foundation
负载均衡。发送申请 可以压倒接收申请 与消息。队列可以管理 不匹配的消息生成和 消费率使接收者 并不是不堪重负。
以下是使用WCF and MSMQ
的示例答案 4 :(得分:0)
请注意,服务示例将在OnStart()处阻止。而是启动一个工作线程:
protected override void OnStart(string[] args)
{
IntPtr handle = this.ServiceHandle;
myServiceStatus.currentState = (int)State.SERVICE_START_PENDING;
SetServiceStatus(handle, ref myServiceStatus);
// Start a separate thread that does the actual work.
if ((workerThread == null) ||
((workerThread.ThreadState &
(System.Threading.ThreadState.Unstarted | System.Threading.ThreadState.Stopped)) != 0))
{
workerThread = new Thread(new ThreadStart(ServiceWorkerMethod));
workerThread.Start();
}
}
然后从worker调用BeginReceive()。