题
我写信给一消息队在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) });
您可以尝试读取消息的BodyStream而不是身体的,是这样的:
StreamReader sr = new StreamReader(m.BodyStream);
string messageBody = "";
while (sr.Peek() >= 0)
{
messageBody += sr.ReadLine();
}
Message recoverableMessage = new Message();
recoverableMessage.Body = "Sample Recoverable Message";
recoverableMessage.Formatter = new XmlMessageFormatter(new String[] {"System.String,mscorlib" });
MessageQueue myQueue = new MessageQueue(@".\private$\teste");
队列必须设置格式化过。
myQueue.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });
似乎访问消息类的Body属性时序列化仅完成。只要你访问Body属性您在留言设定正常工作正确格式化后。
如果你不希望创建一个格式化为每个消息可以设置在队列和每个消息中的格式化器(访问Body属性之前)从队列中的格式化设置格式化属性。
_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"
- 打开每个文件在记事本,并寻找你的队列名(它将最可能的文件,该文件是最近修改)
- 删除该文件并重新启动的信息服务
创建一个基类为你的队列消息项目和[序列化].在应用程序负载高速缓冲存储器的一个列表中的所有你的消息类型,使用这样的事情:
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并不真正喜欢的工作方式。所以我创建了一个背景线和呼叫拦截方法收到在排队,它将再一次回的消息。从有解码的消息是这么简单:
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;
这应该是所有你需要得到很好的执行,类型安全的内容的一体化!
这个工作对我来说读取从远程机器的专用队列:
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();
此工作得非常精细:
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<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