监控队列的最有效方法是什么。
下面的代码是最大的资源:
/// <summary>
/// Starts the service.
/// </summary>
private void StartService()
{
while (true)
{
//the check on count is not thread safe
while (_MessageQueue.Count > 0)
{
Common.IMessage message;
// the call to GetMessageFromQueue is thread safe
if (_MessageQueue.GetMessageFromQueue(out message) == true)
{
if (message.RoutingInfo == Devices.Common.MessageRoutingInfo.ToDevice)
{
_Port.SerialPort.WriteLine(message.Message);
}
if (message.RoutingInfo == Devices.Common.MessageRoutingInfo.FromDevice)
{
OnDeviceMessageReceived(new Common.DeviceMessageArgs(message.Message));
}
}
}
}
}
Start Service在后台线程上运行,对_MessageQueue.Count的调用不是线程安全的,我没有锁定MessageQueue中的count。但是我确实锁定了_MessageQueue.GetMessageFromQueue的实现。 我这样做有效吗?我是否应该在每次队列从0到大于0时提出事件?
答案 0 :(得分:5)
您可能应该在该方法中包含某种类型的线程休眠,否则它将使用100%的CPU。或者,您可以创建一个等待句柄,并在向队列添加消息时进行设置。
答案 1 :(得分:1)
如果我没有错过任何内容 - 您正在_messageQueue.Count属性上忙碌等待。 我会尝试做类似的事情: http://msdn.microsoft.com/en-us/library/yy12yx1f.aspx
答案 2 :(得分:1)
您可以使用NetMsmqBinding
直接将MSMQ消息直接用于WCF,而不是主动轮询队列http://msdn.microsoft.com/en-us/library/ms789008.aspx
希望这有帮助。
答案 3 :(得分:1)
_MessageQueue是否仅在您的代码中使用?然后你可以将它包装在这样的类中:
public class BlockingMessageQueue {
private readonly MyMessageQueue queue;
private readonly Semaphore signal;
public BlockingMessageQueue(MyMessageQueue queue) {
this.queue = queue;
this.signal = new Semaphore(0, int.MaxValue);
}
public void Enqueue(IMessage message) {
lock (this.queue) {
this.queue.Send(message);
}
this.signal.Release();
}
public IMessage Dequeue() {
this.signal.WaitOne();
IMessage message;
lock (this.queue) {
var success = this.queue.GetMessageFromQueue(out message);
Debug.Assert(success);
}
return message;
}
}
Dequeue
将阻止,直到有消息可用,因此如果没有消息可用,则不会浪费周期。
用法示例:
var queue = new BlockingMessageQueue(_MessageQueue);
while (true) {
var message = queue.Dequeue();
if (message.RoutingInfo == Devices.Common.MessageRoutingInfo.ToDevice)
{
_Port.SerialPort.WriteLine(message.Message);
}
else if (message.RoutingInfo == Devices.Common.MessageRoutingInfo.FromDevice)
{
OnDeviceMessageReceived(new Common.DeviceMessageArgs(message.Message));
}
}