我正在用C#中的消息队列写消息,如下所示:
queue.Send(new Message("message"));
我正在尝试阅读以下消息:
Messages messages = queue.GetAllMessages();
foreach(Message m in messages)
{
String message = m.Body;
//do something with string
}
但是我收到一条错误消息,上面写着:“找不到能够读取此消息的格式化程序。”
我做错了什么?
答案 0 :(得分:36)
我通过在每条消息中添加格式化程序来解决问题。将格式化程序添加到队列中不起作用。
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
}
答案 1 :(得分:25)
或者您可以使用
message.Formatter =
new System.Messaging.XmlMessageFormatter(new Type[1] { typeof(string) });
答案 2 :(得分:6)
您可以尝试阅读邮件的正文流而不是正文,如下所示:
StreamReader sr = new StreamReader(m.BodyStream);
string messageBody = "";
while (sr.Peek() >= 0)
{
messageBody += sr.ReadLine();
}
答案 3 :(得分:4)
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" });
答案 4 :(得分:2)
似乎序列化仅在访问Message类的Body属性时完成。只要在设置了正确的Formatter消息后访问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;
答案 5 :(得分:2)
这里的每个人都在提供解决方案方面做得非常出色,而且我刚刚完成了这个问题的斗争,我想把自己的2c放进去,并展示我提出的解决方案非常好。
首先,当我创建队列时,我确保打开这样的权限(我不关心应用程序上下文中的队列安全性......这是一个计算的决定):
queue.SetPermissions("Everyone", MessageQueueAccessRights.FullControl, AccessControlEntryType.Set);
如果没有该行,我将收到各种无法访问的错误,甚至无法从计算机管理屏幕浏览队列。顺便提一下,如果您遇到这种情况,并且您想知道如何杀死您无法访问的队列:
为队列消息项创建基类并将其标记为[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集成!
答案 6 :(得分:1)
这对我来说是从远程机器读取私人队列的:
MessageQueue queue = new MessageQueue(@"FormatName:Direct=OS:MACHINENAME\private$\MyQueueName", QueueAccessMode.Peek);
Message msg = queue.Peek();
StreamReader sr = new StreamReader(msg.BodyStream);
string messageBody = sr.ReadToEnd();
答案 7 :(得分:0)
这很好用:
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();
}
答案 8 :(得分:0)
添加格式化程序解决了我的问题:
public void ReceiveAsync<T>(MqReceived<T> 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