消息队列

发布时间 2023-12-18 17:18:29作者: 四月柳巷
首先使用消息队列前,我们需要知道,消息队列是用来发送、接收数据的一个容器,简单的说:我们在某宝上买东西,这中间有一个快递的过程,而大多数情况下,我本人选择将我买的东西寄到某个代收点,派送员只需要按照我的要求将东西放到代收点就可以了,之后我有时间了才自己去取。消息队列就类似于这个代收点了,它能存取数据。那么既然存取数据,那我们总得先知道这玩意在哪里,不能盲目瞎搞。
 
博主的操作系统是WIN10的,所以此处写WIN10的操作步骤:
 
打开“此电脑”-->左上角点击“计算机”-->点击“管理”

 

然后进入了计算机管理界面
 
点击左边的“服务和应用程序”-->“消息队列”。此时会看到三个空的文件夹(如果别的地方操作过的话也有可能不是空的),分别是“传出队列”、“专用队列”和“系统队列”,这三个文件夹就是我们所要的“快递代收点”了。

 

注意:如果没看到“消息队列”这个选项,那就是这东西在这电脑上还没使用过,没关系,一会编程的时候创建就会显示出来了(我印象中一开始我也没有这个选项,写了代码后就有了)
知道这东西在哪里后,开始进入正题。C#中使用消息队列需要添加新的引用System.Messaging

 

添加引用后在代码里添加命名空间就可以开始了

 

这里,我们新建一个控制台程序,代码如下:

static void Main(string[] args)
{
    string msgPath = ".\\Private$\\MyMsg";  //一个名称为“mymsg”的专用队列的路径字符串
    string studentName = "T-Max";  //要写入消息消息队列的信息
    SendMsg(msgPath, studentName);
    Console.WriteLine("发送成功");
    Console.ReadLine();
}
 
private static void SendMsg(string mQPath,string studentName)
{
    //先判断这个消息队列是否存在,如果存在则直接实例化对象,如果不存在则创建改消息队列
    MessageQueue mq = (MessageQueue.Exists(mQPath)) ? (new MessageQueue(mQPath)) : (MessageQueue.Create(mQPath)); 
    mq.Send(studentName);  //将消息发送到消息队列
}

 

此处,我们使用的是“专用队列”(Private$),至于与其他的有什么不同,不是本文重点,不在本文章赘述。运行程序后得到的控制台结果为

 

重新打开“计算机管理”,发现专用队列中多了一个“mymsg”的文件夹,在该文件夹底下还有两个文件夹,分别是“队列消息”和“日志消息”,都双击一遍发现“日志消息”是空的,而“队列消息”有一个“标签”

 

如上图,右键该标签点击“属性”,在“常规”里可以看到此条消息的“发送时间”、“到达时间”等各种详细信息,然后接着点击“正文”,我们就可以看到刚在代码里发送的消息了

 

这说明,我们已经通过代码成功的将消息发送到了消息队列中并保存在了计算机里。
完成了“存”的操作,现在开始做“取”的操作。
 
此处介绍两种方法,一种为异步读取,一种为同步读取。
 
异步读取代码如下:
static void Main(string[] args)
{
    string msgPath = ".\\Private$\\MyMsg";  //要读取的消息队列路径
    ReceiveMsg(msgPath);
    Console.ReadLine();
}
 
//异步读取
private static void ReceiveMsg(string msgPath)
{
    if (MessageQueue.Exists(msgPath))
    {
        MessageQueue mq = new MessageQueue(msgPath);
        mq.ReceiveCompleted += new ReceiveCompletedEventHandler(ReceiveMethon);
        mq.BeginReceive(MessageQueue.InfiniteTimeout);
        Console.WriteLine("已接收数据 ");
    }
}
 
static readonly XmlMessageFormatter f = new XmlMessageFormatter(new Type[] { typeof(String) }); //格式
private static void ReceiveMethon(object sender, ReceiveCompletedEventArgs e)
{
    Message m = e.Message;
    m.Formatter = f;  //指定格式化程序
    Console.WriteLine(m.Body.ToString());
}
同步读取代码如下:

static void Main(string[] args)
{
    string msgPath = ".\\Private$\\MyMsg";  //要读取的消息队列路径
    ReceiveMsg(msgPath);
    Console.ReadLine();
}
 
static readonly XmlMessageFormatter f = new XmlMessageFormatter(new Type[] { typeof(String) }); //格式
 
//同步读取
private static void ReceiveMsg(string msgPath)
{
    if (MessageQueue.Exists(msgPath))
    {
        MessageQueue mq = new MessageQueue(msgPath);
        Message m = mq.Receive();
        m.Formatter = f; //指定格式化程序
        Console.WriteLine(m.Body.ToString());
        Console.WriteLine("已接收数据 ");
    }
}
这里简单说一下两种方式读取的区别,同步读取数据的话,会堵塞当前线程,直到读到数据为止才继续运行之后的程序,异步读取的话就避免了这个问题。如果读取的数据量小、速度快,为了编写代码方便可选择同步读取,如果读取的数据量大、速度慢,则建议使用异步读取。
运行程序后,控制台得到结果为:

 

这说明,成功的读取到了消息队列中的数据。
 
然后,再次打开“计算机管理”,依旧找到我们的“mymsg”,双击“队列消息”,发现标签已经消失了(如果没消失,F5刷新一下)

 

得是非常的“快递代收点”呢?快递被取走了肯定不在了。消息队列有点像我们常见的数据库,能进行数据的存取,但是与数据库其中一点不同的就是消息队里中的消息被读取后就会被销毁,不需要我们手动删除。