消息队列错误:找不到能够读取消息的格式化程序
我正在使用C#将消息写入消息队列,如下所示:
queue.Send(new Message("message"));
我正在尝试阅读如下消息:
Messages messages = queue.GetAllMessages(); foreach(Message m in messages) { String message = m.Body; //do something with string }
但是我收到一条错误消息,上面写着:“找不到能够读取此消息的格式化程序。”
我究竟做错了什么?
我通过在每条消息中添加格式化程序来解决问题。 将格式化程序添加到队列不起作用。
Messages messages = queue.GetAllMessages(); foreach(Message m in messages) { m.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" }); String message = m.Body; //do something with string }
或者你可以使用
message.Formatter = new System.Messaging.XmlMessageFormatter(new Type[1] { typeof(string) });
您可以尝试阅读消息的正文流而不是正文,如下所示:
StreamReader sr = new StreamReader(m.BodyStream); string messageBody = ""; while (sr.Peek() >= 0) { messageBody += sr.ReadLine(); }
似乎只有在访问Message类的Body属性时才会进行序列化。 只要您在消息上设置正确的格式化程序后访问Body属性它就可以正常工作。
如果您不想为每条消息创建Formatter,可以在队列上设置Formatter,并为每条消息设置(在访问Body属性之前),从队列的Formatter设置Formatter属性。
_queue.Send(new Message() { Formatter = _queue.Formatter, Body = myData } ); var msg = _qeueu.Receive(); msg.Formatter = _queue.Formatter; var myObject = (MyClass) msg.Body;
这里的每个人都在提供解决方案方面做得非常出色,而且我刚刚完成了这个问题的斗争,我想把自己的2c放进去,并展示我提出的解决方案非常有效。
首先,当我创建队列时,我确保打开这样的权限(我不关心应用程序上下文中的队列安全性……这是一个计算的决定):
queue.SetPermissions("Everyone", MessageQueueAccessRights.FullControl, AccessControlEntryType.Set);
如果没有该行,我将收到各种无法访问的错误,甚至无法从计算机管理屏幕浏览队列。 顺便说一句,如果你遇到这种情况,并且想知道如何杀死你无权访问的队列:
- 停止服务“消息队列”
- 转到“C: Windows System32 msmq storage lqs”
- 在记事本中打开每个文件并查找您的队列名称(它很可能是最近修改过的文件)
- 删除该文件并重新启动Messaging服务
为队列消息项创建基类并将其标记为[Serializable]。 在应用程序加载时,使用以下内容缓存所有消息类型的列表:
var types = typeof(QueueItemBase).Assembly .GetTypes() .Where(t => typeof(QueueItemBase).IsAssignableFrom(t) && t.IsAbstract == false) .ToArray(); ... // Create and cache a message formatter instance _messageFormatter = new XmlMessageFormatter(types);
现在您已准备好开始接收消息。 我的第一直觉就是对消息进行轮询,但是api并不喜欢那样工作。 所以我创建了一个后台线程,并在队列上调用阻塞方法Receive,一旦有消息可以返回。 从那里解码消息就像这样简单:
var message = queue.Receive(); if (message == null) continue; // Tell the message about our formatter containing all our message types before we // try and deserialise message.Formatter = _messageFormatter; var item = message.Body as QueueItemBase;
这应该是您需要的所有实现,类型安全的MSMQ集成!
Message recoverableMessage = new Message(); recoverableMessage.Body = "Sample Recoverable Message"; recoverableMessage.Formatter = new XmlMessageFormatter(new String[] {"System.String,mscorlib" }); MessageQueue myQueue = new MessageQueue(@".private$teste");
队列也必须设置为Formatter。
myQueue.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });
这对我来说是从远程机器读取私有队列:
MessageQueue queue = new MessageQueue(@"FormatName:Direct=OS:MACHINENAMEprivate$MyQueueName", QueueAccessMode.Peek); Message msg = queue.Peek(); StreamReader sr = new StreamReader(msg.BodyStream); string messageBody = sr.ReadToEnd();
这很好用:
static readonly XmlMessageFormatter f = new XmlMessageFormatter(new Type[] { typeof(String) }); private void Client() { var messageQueue = new MessageQueue(@".Private$SomeTestName"); foreach (Message message in messageQueue.GetAllMessages()) { message.Formatter = f; Console.WriteLine(message.Body); } messageQueue.Purge(); }
添加格式化器解决了我的问题:
public void ReceiveAsync(MqReceived mqReceived) { try { receiveEventHandler = (source, args) => { var queue = (MessageQueue)source; using (Message msg = queue.EndPeek(args.AsyncResult)) { XmlMessageFormatter formatter = new XmlMessageFormatter(new Type[] { typeof(T) }); msg.Formatter = formatter; queue.ReceiveById(msg.Id); T tMsg = (T)msg.Body; mqReceived(tMsg); } queue.BeginPeek(); }; messageQueu.PeekCompleted += receiveEventHandler; messageQueu.BeginPeek(); } catch (Exception e) { Console.WriteLine(e.Message); } }
您可以在github上看到示例代码和msmq库: https : //github.com/beyazc/MsmqInt
上述就是C#学习教程:消息队列错误:找不到能够读取消息的格式化程序分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/949419.html