C# 消息队列错误:找不到能够读取消息的格式化程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/655276/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Message Queue Error: cannot find a formatter capable of reading message
提问by macleojw
I'm writing messages to a Message Queue in C# as follows:
我正在将消息写入 C# 中的消息队列,如下所示:
queue.Send(new Message("message"));
I'm trying to read the messages as follows:
我正在尝试按如下方式阅读消息:
Messages messages = queue.GetAllMessages();
foreach(Message m in messages)
{
String message = m.Body;
//do something with string
}
However I'm getting an error message which says: "Cannot find a formatter capable of reading this message."
但是,我收到一条错误消息,内容为:“找不到能够读取此消息的格式化程序。”
What am I doing wrong?
我究竟做错了什么?
采纳答案by macleojw
I solved the problem by adding a formatter to each message. Adding a formatter to the queue didn't work.
我通过向每条消息添加格式化程序解决了这个问题。向队列添加格式化程序不起作用。
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
}
回答by prime23
Or you can use
或者你可以使用
message.Formatter =
new System.Messaging.XmlMessageFormatter(new Type[1] { typeof(string) });
回答by selalerer
It seems that the serialization is only done when accessing the Body
property of the Message
class. As long as you access the Body
property after you set on the message the right Formatter
it works fine.
似乎只有在访问类的Body
属性时才会进行序列化Message
。只要您Body
在设置消息后访问该属性,Formatter
它就可以正常工作。
If you prefer not to create a Formatter
for each message you can set the Formatter
on the queue and for each message (before accessing the Body property) set the Formatter
property from the Formatter
of the queue.
如果您不想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;
回答by felbus
you could try reading the bodystream of the message instead of the body, like this:
您可以尝试读取消息的正文流而不是正文,如下所示:
StreamReader sr = new StreamReader(m.BodyStream);
string messageBody = "";
while (sr.Peek() >= 0)
{
messageBody += sr.ReadLine();
}
回答by Mr Milk
Message recoverableMessage = new Message();
recoverableMessage.Body = "Sample Recoverable Message";
recoverableMessage.Formatter = new XmlMessageFormatter(new String[] {"System.String,mscorlib" });
MessageQueue myQueue = new MessageQueue(@".\private$\teste");
Queue must be set Formatter too.
队列也必须设置格式化程序。
myQueue.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });
回答by harveyt
this works very fine:
这工作得很好:
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();
}
回答by Paul Carroll
Everyone here has done a fantastic job at providing solutions, and having just finished battling this problem myself I wanted to throw my own 2c in and show the solution I came up with that works very well.
这里的每个人都在提供解决方案方面做得非常出色,我自己刚刚解决了这个问题,我想投入我自己的 2c 并展示我想出的解决方案非常有效。
Firstly when the queue is created I make sure I open up the permissions like so (I'm not concerned about queue security in the context of our application... this is a calculated decision):
首先,当创建队列时,我确保我像这样打开权限(我不关心我们应用程序上下文中的队列安全性......这是一个经过计算的决定):
queue.SetPermissions("Everyone", MessageQueueAccessRights.FullControl, AccessControlEntryType.Set);
Without that line I would receive all sorts of inaccessible errors and couldn't even browse the queue from the computer management screen. Incidentally if that happens to you and you're wondering how to kill the queue that you don't have access to just:
如果没有那条线,我会收到各种无法访问的错误,甚至无法从计算机管理屏幕浏览队列。顺便说一句,如果这种情况发生在您身上并且您想知道如何终止您无权访问的队列:
- Stop the service "Message Queueing"
- Goto "C:\Windows\System32\msmq\storage\lqs"
- Open each file in notepad and look for your queue name (it will most likely be the file that was most recently modified)
- Delete that file and restart the Messaging service
- 停止服务“消息队列”
- 转到“C:\Windows\System32\msmq\storage\lqs”
- 在记事本中打开每个文件并查找您的队列名称(它很可能是最近修改的文件)
- 删除该文件并重新启动消息服务
Create a base class for your queue message items and mark it [Serializable]. On application load cache a list of all your message types using something like this:
为您的队列消息项创建一个基类并将其标记为 [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);
Now you're ready to start receiving messages. My first instinct was to poll for messages, but the api doesn't really like working that way. So I create a background thread and call the blocking method Receive on the queue which will return once a message is available. From there decoding the message is as simple as:
现在您已准备好开始接收消息。我的第一直觉是轮询消息,但 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;
And that should be all you need to get nicely implemented, typesafe MSMQ integration!
这应该是您获得良好实现的、类型安全的 MSMQ 集成所需的全部内容!
回答by Contango
This worked for me to read a private queue from a remote machine:
这对我从远程机器读取私人队列有用:
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();
Update 2019-11-29
更新 2019-11-29
Don't use Microsoft Message Queue (MSMQ). Just don't. It is both deprecated, and bottom of the pile in terms of anything useful, performant or even remotely well designed.
不要使用 Microsoft 消息队列 (MSMQ)。只是不要。它已被弃用,并且在任何有用的、高性能的甚至远程设计良好的方面都处于劣势。
回答by cahit beyaz
Adding formatter solved my issue:
添加格式化程序解决了我的问题:
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);
}
}
You can see sample code and msmq library on github: https://github.com/beyazc/MsmqInt
你可以在github上看到示例代码和msmq库:https: //github.com/beyazc/MsmqInt