消息队列错误:找不到能够读取消息的格式化程序

时间:2009-03-17 17:35:35

标签: c# message-queue

我正在用C#中的消息队列写消息,如下所示:

queue.Send(new Message("message"));

我正在尝试阅读以下消息:

Messages messages = queue.GetAllMessages();
foreach(Message m in messages)
{
  String message = m.Body;
  //do something with string
}

但是我收到一条错误消息,上面写着:“找不到能够读取此消息的格式化程序。”

我做错了什么?

9 个答案:

答案 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);

如果没有该行,我将收到各种无法访问的错误,甚至无法从计算机管理屏幕浏览队列。顺便提一下,如果您遇到这种情况,并且您想知道如何杀死您无法访问的队列:

  1. 停止服务"消息队列"
  2. 转到" C:\ Windows \ System32 \ msmq \ storage \ lqs"
  3. 在记事本中打开每个文件并查找您的队列名称(它很可能是最近修改过的文件)
  4. 删除该文件并重新启动Messaging服务
  5. 为队列消息项创建基类并将其标记为[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