C#基础教程(三)消息队列——MSMQ
Net使⽤消息队列,借助windows组件来存储要完成的⼀系列任务,不⽤程序使⽤同⼀个队列,⽅便不同程序之间的数据共享和协作。
队列分事务性队列和⾮事务性队列,默认创建的是⾮事务性队列。那么什么是事务性队列呢?事务性队列将消息保存在磁盘上,实现了持久
化,也就是说当我们关机,断电后,下次再启动机器,我们的消息依然保存在队列⾥⾯,⽽⾮事务性队列则将消息保存在内存中,也就是说
我重启电脑后,队列⾥⾯的消息将不存在了。
(⼀) 复杂消息收发(对象)
static void Main(string[] args)
{
const string queueName = @".\Private$\jiyiqin";
MessageQueue mq = null;
if (!MessageQueue.Exists(queueName))// 如果指定的路径queueName中不存在队列,那么在该路径,即queueName中创建⼀个消息队列。jiyiqin就是你想要创建    {
mq = MessageQueue.Create(queueName);//创建名称jiyiqin的消息队列的实例。
Console.WriteLine("创建消息队列完成:" + queueName);
}
else  //如果消息队列jiyiqin已经存在,那么创建该消息队列的⼀个实例
{
mq = new MessageQueue(queueName);//创建名称jiyiqin的消息队列的实例。
}
mq.SetPermissions("Administrator", MessageQueueAccessRights.FullControl);
mq.SetPermissions("ANONYMOUS LOGON", MessageQueueAccessRights.FullControl);
mq.SetPermissions("Everyone", MessageQueueAccessRights.FullControl);
Message msgTx = new Message();
msgTx.Formatter = new XmlMessageFormatter(new Type[] { typeof(MsgModel) });
msgTx.Body = new MsgModel("1", "消息1");
mq.Send(msgTx);
Console.Write("成功发送消息," + DateTime.Now + "");
if (mq.GetAllMessages().Length > 0)
{
System.Messaging.Message message = mq.Receive(TimeSpan.FromSeconds(5));
if (message != null)
{
message.Formatter = new System.Messaging.XmlMessageFormatter(new Type[] { typeof(MsgModel) });//消息类型转换
MsgModel msg = (MsgModel)message.Body;
Console.WriteLine(msg.id+msg.Name);
Console.Read();
}
}
}
(⼆) 本地发/收
//发送
static void Main(string[] args)
{
MessageQueue MSMQ = CreateMessageQueue(@".\private$\jiyiqin");
MSMQ.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
Console.WriteLine("是否继续发送消息:Y/N?");
string cmd = Console.ReadLine();
while (cmd.Equals("Y"))
{
Sender(MSMQ);
Console.WriteLine("是否继续发送消息:Y/N?");
cmd = Console.ReadLine();
}
Console.WriteLine("按任意键以停⽌...");
Console.ReadKey();
}
private static void Sender(MessageQueue MSMQ)
{
try
{
string random = new Random().Next(0,100).ToString();
string obj = string.Format("{0} 发送⽅:{1}",DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), random);        MSMQ.Send(obj, MessageQueueTransactionType.Single);
Console.WriteLine(obj);
}
catch (Exception ex)
{
Console.WriteLine(string.Format("{0} 发送⽅:{1}",
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), ex.Message));
}
}
public static MessageQueue CreateMessageQueue(string path)
{
MessageQueue mq = null;
if (MessageQueue.Exists(path))
{
//存在,创建队列实例
mq = new MessageQueue(path);
}
else
{
//不存在,创建消息队列
mq = MessageQueue.Create(path, true);
}
return mq;
}
消息队列即使接收端没开启,消息仍会阻塞在队列中,等接收端开启,就可以⼀条条加载消息。(三) 异地指定队列增加消息
异地指定队列增加消息,我们测试同⼀局域⽹内两台计算机发/收。
///接收端 ip 192.168.2.240
static void Main(string[] args)
{
MessageQueue MSMQ = CreateMessageQueue(@".\private$\jiyiqin");
MSMQ.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
Receiver(MSMQ);
}
private static void Receiver(MessageQueue MSMQ)
{
while (true)
{
try
{
Message m = MSMQ.Receive(MessageQueueTransactionType.Single);
Console.WriteLine(string.Format("{0} 接收⽅:[{1}]",DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), m.Body.ToString()));
}
catch (Exception ex)
{
Console.WriteLine(string.Format("{0} 接收⽅:{1}",
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), ex.Message));
}
}
}
public static MessageQueue CreateMessageQueue(string path)
{
MessageQueue mq = null;
if (MessageQueue.Exists(path))
{
mq = new MessageQueue(path);
}
else
{
mq = MessageQueue.Create(path, true);
}
return mq;
}
远程队列的路径格式:string path = @"Formatname:DIRECT=tcp:192.168.2.240\Private$\jiyiqin";  关键字不区分⼤⼩写
MSMQ 判断队列是否存在的⽅法(MessageQueue.Exists(string path))和创建队列(MessageQueue.Create(string path)),都是不⽀持远程队列的。
1.使⽤Exists⽅法会出现错误【⽆法确定具有指定格式名的队列是否存在】
2.使⽤Create⽅法会出现错误【⽆法创建路径为 FormatName:DIRECT=tcp:192.168.2.240\Private$\jiyiqin】
3.由于前两条的限制,如果要访问远程专⽤队列,则必须保证事先在远程机器上该队列是存在的。
static void Main(string[] args)
{
MessageQueue MSMQ = CreateMessageQueue(@"FormatName:Direct=TCP:192.168.2.240\Private$\jiyiqin");
MSMQ.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
Console.WriteLine("是否继续发送消息:Y/N?");
string cmd = Console.ReadLine();
while (cmd.Equals("Y"))
{
Sender(MSMQ);
Console.WriteLine("是否继续发送消息:Y/N?");
cmd = Console.ReadLine();
}
Console.WriteLine("按任意键以停⽌...");
Console.ReadKey();
}
private static void Sender(MessageQueue MSMQ)
{
try
{
string random = new Random().Next(0,100).ToString();
string obj = string.Format("{0} 发送⽅:{1}",DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), random);
MSMQ.Send(obj, MessageQueueTransactionType.Single);
Console.WriteLine(obj);
}
catch (Exception ex)
{
Console.WriteLine(string.Format("{0} 发送⽅:{1}",
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), ex.Message));
}
}
public static MessageQueue CreateMessageQueue(string path)
{
MessageQueue mq = null;
// MessageQueue.Exists(path)会报错
if (true)
{
//存在,创建队列实例writeline教程
mq = new MessageQueue(path);
}
else
{
//不存在,创建消息队列
mq = MessageQueue.Create(path, true);
}
return mq;
}
当发送消息到远程队列时,系统会在本机的传出队列下创建⼀个临时队列,每发送⼀条消息,该消息都会先存在临时队列中,这样做的⽬的是防⽌因远程队列⽆法访问⽽丢失消息,。
总结
特别注意的是,如果远程机器不能成功连接,则消息就⼀直在临时队列中存放;如果能成功连接,即使要访问的队列并不存在,消息发送程序也不会报错,并且临时队列中的消息会删除。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。