多线程操作消息队列

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情
 1.       消息队列(Message Queue):
a.       添加System.Messaging.dll.
b.       简介
利用 MSMQMicrosoft Message Queue),应用程序开发人员可以通过发送和接收消息方便地与应用程序进行快速可靠的通信。消息处理为您提供了有保障的消息传递和执行许多业务处理的可靠的防故障方法。
MSMQ与XML Web Services和.Net Remoting一样,是一种分布式开发技术。但是在使用XML Web Services或.Net Remoting组件时,Client端需要和Server端实时交换信息,Server需要保持联机。MSMQ则可以在Server离线的情况下工作,将Message临时保存在Client端的消息队列中,以后联机时再发送到Server端处理。
显然,MSMQ不适合于Client需要Server端及时响应的这种情况,MSMQ以异步的方式和Server端交互,不用担心等待Server端的长时间处理过程。
虽然XML Web Services和.Net Remoting都提供了[OneWay]属性来处理异步调用,用来解决Server端长方法调用长时间阻碍Client端。但是不能解决大量Client负载的问题,此时Server接受的请求快于处理请求。
一般情况下,[OneWay]属性不用于专门的消息服务中。
c.       .Net 环境下编写简单的 Message Queue 程序
(1)先安装Message Queuing Services
通过Control Panel,“Add/Remove Programs” – “Add/Remove Windows Components”步骤安装MSMQ。
MSMQ可以安装为工作组模式或域模式。如果安装程序没有找到一台运行提供目录服务的消息队列的服务器,则只可以安装为工作组模式,此计算机上的“消息队列”只支持创建专用队列和创建与其他运行“消息队列”的计算机的直接连接。
(2)配置MSMQ
打开Computer Management – Message Queuing,在Private Queues下创建MSMQDemo队列
(3)编写代码-简单演示MSMQ对象
MessageQueue 类是“消息队列”周围的包装。MessageQueue 类提供对“消息队列”队列的引用。可以在 MessageQueue 构造函数中指定一个连接到现有资源的路径,或者可在服务器上创建新队列。在调用 Send、Peek 或 Receive 之前,必须将 MessageQueue 类的新实例与某个现有队列关联。
MessageQueue 支持两种类型的消息检索:同步和异步。同步的 Peek Receive 方法使进程线程用指定的间隔时间等待新消息到达队列。异步的 BeginPeek BeginReceive 方法允许主应用程序任务在消息到达队列之前,在单独的线程中继续执行。这些方法通过使用回调对象和状态对象进行工作,以便在线程之间进行信息通讯。
private void btnSendMessage_Click(object sender, System.EventArgs e)
        {
            
//Open Queue
            System.Messaging.MessageQueue queue=new System.Messaging.MessageQueue("./Private$/MSMQDemo");
            
//Create Message
            System.Messaging.Message message=new System.Messaging.Message();
            message.Body
=txtMessage.Text.Trim();
            message.Formatter
=new System.Messaging.XmlMessageFormatter(new Type[]{typeof(string)});
            
//Put Message Into Queue
            queue.Send(message);
        }
        
//同步接收
        private void btnReceiveMessage_Click(object sender, System.EventArgs e)
        {
            
try
            {
                
//Open Queue
                System.Messaging.MessageQueue queue=new System.Messaging.MessageQueue("./Private$/MSMQDemo");
                
//Receive message,同步的Receive方法阻塞当前执行线程,直到一个message可以得到
                lock(queue)
                {
                    System.Messaging.Message message
=queue.Receive(new TimeSpan(0,0,0,1),System.Messaging.MessageQueueTransactionType.Single);
                    message.Formatter
=new System.Messaging.XmlMessageFormatter(new Type[]{typeof(string)});
                    txtReceiveMessage.Text
=message.Body.ToString();
                }
            }
            
catch(System.Messaging.MessageQueueException ex)
            {
                
//超时
                MessageBox.Show(ex.MessageQueueErrorCode.ToString());
            }
    }
结束.

        
//异步接收
        private void Receive1_Click(object sender, System.EventArgs e)
        {
            System.Messaging.MessageQueue mq1
=new System.Messaging.MessageQueue("./Private$/MSMQDemo");
            mq1.ReceiveCompleted
+=new System.Messaging.ReceiveCompletedEventHandler(ReceiveEvt);
            mq1.BeginReceive();
        }

        
private void ReceiveEvt(object source,System.Messaging.ReceiveCompletedEventArgs asyncResult)
        {
            
try
            {
                System.Messaging.MessageQueue mqReceive
=(System.Messaging.MessageQueue)source;
                System.Messaging.Message m
=mqReceive.EndReceive(asyncResult.AsyncResult);
                
//此事m为异步接收到的消息
                
//在此插入处理消息的代码
                m.Formatter=new System.Messaging.XmlMessageFormatter(new Type[]{typeof(string)});
                txtReceiveMessage.Text
=m.Body.ToString();
                mqReceive.BeginReceive();
//接收下一次事件
            }
            
catch(System.Messaging.MessageQueueException e)
            {
                System.Windows.Forms.MessageBox.Show(e.MessageQueueErrorCode.ToString());
                System.Windows.Forms.MessageBox.Show(e.Message);
            }
    }

好处:当第二次点发送消息的时候,自动接收。

D.在后台写的操作类。

        /// <summary>
        
/// 检查队列,如果队列不存在,则建立 
        
///
 队列名称
        
/// </summary>

        
/// <param name="path">路径</param>
        private static void EnsureQueueExists(string path)
        {
            
if(!
System.Messaging.MessageQueue.Exists(path))
            {
                System.Messaging.MessageQueue.Create(path);
                System.Messaging.MessageQueue mqTemp
=new
 System.Messaging.MessageQueue(path);
                mqTemp.SetPermissions(
"Everyone"
,System.Messaging.MessageQueueAccessRights.FullControl);
                
///不知道该给什么样的权限好,所以就给了Everone全部权限了,当然大家最好自己控制一下

            }
        }

        
/// <summary>

        
/// 发送对象到队列中
        
///
 队列名称,因为队列名称在一个应用中应该不改变的,所以大家最好写在配置文件中
        
///
 要发出去的对象
        
/// </summary>

        
/// <param name="QueuePath"></param>
        
/// <param name="MessageText"></param>
        public static void SendQueue(string QueuePath,string MessageText)
        {
            System.Messaging.MessageQueue mqSend
=new System.Messaging.MessageQueue(QueuePath,false
);
            EnsureQueueExists(QueuePath);
            System.Messaging.Message sq
=new
 System.Messaging.Message();
            sq.Body
=
MessageText.Trim();
            sq.Formatter
=new System.Messaging.XmlMessageFormatter(new Type[]{typeof(string
)});
            mqSend.Send(sq);
        }

        
/// <summary>

        
/// 从队列中取出对象列表
        
///
 队列名称
        
///
 不知道怎么用
        
/// </summary>

        
/// <param name="QueuePath"></param>
        
/// <returns></returns>
        public static System.Collections.ArrayList GetMessage(string QueuePath)
        {
            System.Messaging.Message sq
=new
 System.Messaging.Message();
            System.Messaging.MessageQueue mq
=new System.Messaging.MessageQueue(QueuePath,false
);
            mq.Formatter
=new System.Messaging.XmlMessageFormatter(new Type[]{typeof(string
)});
            System.Messaging.Message[] arrM
=
mq.GetAllMessages();
            mq.Close();
            System.Collections.ArrayList al
=new
 System.Collections.ArrayList();
            
foreach(System.Messaging.Message m in
 arrM)
            {
                sq
=m.Body as
 System.Messaging.Message;
                al.Add(sq);
            }
            
return
 al;
        }

        
/// <summary>

        
/// 得到计算机消息队列中的数量,做循环进行计数
        
/// </summary>

        
/// <param name="QueuePath"></param>
        
/// <returns></returns>
        public static uint Count(string QueuePath)
        {
            
//变量,存放数量

            uint numberItems=0;
            
//连接到队列

            System.Messaging.MessageQueue mq=new System.Messaging.MessageQueue(QueuePath);
            System.Messaging.MessageEnumerator myEnumerator
=
mq.GetMessageEnumerator();
            
while
(myEnumerator.MoveNext())
            {
                numberItems
++
;
            }
            
return
 numberItems;
        }

E.后台写的利用多线程监听的操作类。

private string m_MachineName;
        
private string
 m_QueueName;
        
public bool flag=true
;

        
/// <summary>

        
/// 重载构造函数,接收必要的队列信息
        
/// </summary>

        
/// <param name="MachineName"></param>
        
/// <param name="QueueName"></param>
        public MQListen(string MachineName,string QueueName)
        {
            m_MachineName
=
MachineName;
            m_QueueName
=
QueueName;
        }

        
public void
 Listen()
        {
            
//创建一个MessageQueue对象

            System.Messaging.MessageQueue MQ=new System.Messaging.MessageQueue();
            
//设置MessageQueue对象的路径属性

            MQ.Path=m_MachineName+"/private$/"+m_QueueName;
            
//创建一个Message对象

            System.Messaging.Message message=new System.Messaging.Message();
            
//重复上述步骤,直到收到中止

            while(flag)
            {
                
try

                {
                    
//休眠以在中断发出时捕捉中断
                    System.Threading.Thread.Sleep(100);
                    
//
将Message对象设置为与接收函数的结果相等
                    
//持续时间(天,时,分钟,秒)

                    message=MQ.Receive(new TimeSpan(0,0,10,10));
                    
//显示已接受消息的标签

                    System.Windows.Forms.MessageBox.Show("Label:"+message.Label);
                }
                
catch
(System.Threading.ThreadInterruptedException e)
                {
                    
//从主线程捕捉ThreadInterrupt并退出

                    Console.WriteLine("Exiting Thread");
                    message.Dispose();
                    MQ.Dispose();
                    
break
;
                }
                
catch
(Exception GenericException)
                {
                    
// 捕捉接收过程中抛出的所有异常。

                    Console.WriteLine(GenericException.Message);
                }
            }
        }

启动和终止线程操作同步消息队列:
    简单:
            启动:        MultiThreadedMQListener.MQListen objMQListen
=new WinFormExample1._0320.MultiThreadedMQListener.MQListen(".","MSMQDemo"
);
            System.Threading.Thread thread
=new System.Threading.Thread(new
 System.Threading.ThreadStart (objMQListen.Listen));
            t.Start();
            终止:            MultiThreadedMQListener.MQListen objMQListen
=new WinFormExample1._0320.MultiThreadedMQListener.MQListen(".","MSMQDemo"
);
            objMQListen.flag
=false
;
    复杂(线程池):
        
private void
 StartThreads()
        {
            
int LoopCounter;//线程计数

            StopListeningFlag=false;// 跟踪辅助线程是否应当终止的标志。
            
//将一个包含 5 个线程的数组声明为辅助线程。

            Thread[] ThreadArray=new Thread[5];
            
//声明包含辅助线程的所有代码的类。

            MQListen objMQListen=new MQListen(server.Text,Queue.Text);
            
for(LoopCounter=0;LoopCounter<ThreadArray.Length;LoopCounter++
)
            {
                
//创建一个 Thread 对象。

                ThreadArray[LoopCounter]=new Thread(new ThreadStart(objMQListen.Listen));
                
//启动线程将调用 ThreadStart 委托。

                ThreadArray[LoopCounter].Start();
            }
            statusBar1.Text
=LoopCounter.ToString()+" listener threads started"
;
            
while(!
StopListeningFlag)
            {
                
//
等待用户按下停止按钮。
                
//在等待过程中,让系统处理其他事件。

                System.Windows.Forms.Application.DoEvents();
            }
            statusBar1.Text
="Stop request received,stopping threads"
;
            
//向每个线程发送一个中断请求。

            for(LoopCounter=0;LoopCounter<ThreadArray.Length;LoopCounter++)
            {
                ThreadArray[LoopCounter].Interrupt();
            }
            statusBar1.Text
="All Threads have been Stopped"
;
        }

        
private bool StopListeningFlag=false
;

        
private void start_Click(object
 sender, System.EventArgs e)
        {
            statusBar1.Text
="Starting Threads"
;
            StartThreads();
        }

        
private void stop_Click(object
 sender, System.EventArgs e)
        {
            StopListeningFlag
=true
;
        }

异步操作消息队列:

先声明一个  
 
System.Threading.ManualResetEvent socketEvent=new System.Threading.ManualResetEvent(false);   
 
socketEvent.Reset();

BeginReceive();监听;  
 
然后socketEvent.WaitOne();

回调函数中  
 
socketEvent.Set();  然后使用EndReceive ()来完成数据报的接收  

linux下多线程间通信之信号量,消息队列的综合运用 一、消息队列介绍 消息队列是消息的链接表,存放在内核中。其实质上就是一个内核链表,消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度。对消息队列有写权限的进程可以按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读出消息。消息队列是随内核持续的并和进程相关, 系统中 阅读详情

相关推荐

异步处理优化:多线程线程池与消息队列的选择与应用

本文讨论了两种常见的异步处理方式:多线程线程池和消息队列(MQ)。通过将非核心逻辑异步化,可以提升系统的性能和响应速度。多线程线程池适用于本地并发任务,适合需要快速响应的场景,但无法处理跨服务任务。消息队列则适用于分布式系统,能够解耦服务并保证任务的可靠性和顺序性,适合处理高并发和高可靠性要求的任务。文章提供了实际代码示例,帮助开发者根据业务需求选择合适的异步处理方式。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 170万+

多线程使用消息队列

多线程使用消息队列

C#中实现高效消息队列多线程集成

在这个命名空间中,类是核心类,它提供了丰富的属性和方法来管理消息队列。主要方法包括:Send:用于发送消息到队列。Receive:用于从队列中接收消息。Peek:用于查看队列中的消息而不移除它。Create:用于创建一个新的消息队列。Delete:用于删除一个存在的消息队列。还有如Message类,它代表了消息的内容和属性。消息可以通过构造函数创建,并设置如标签、正文、优先级和超时等属性。

weixin_29607511的博客 1560

小目标检测(3)——msgqueue多线程通信和多线程互斥编程

* 这里使用了两个队列,一个是生产者放入消息的队列,一个是消费者取走消息的队列,两个队列进行互换,实现消息的传递。 * 之前虽然接触过进程锁之类的编程,但是都是使用自己定义的结构体来实现进程的互斥访问,并没有使用过std::mutex进行编程,而且线程也是自己定义的一些类的实体。 * 所以,这里首先介绍一下线程的基本要素,然后介绍一下std::mutex信号量类,接着在介绍一下std::condition_variable同步线程类的使用,最后在介绍具体的实现过程。

Blackoutdragon的博客 706

前端请求队列,解决多个请求同时请求一个接口导致阻塞的问题

但是在实际测试过程中,发现每一个vue文件进入到queryEchartsData后,在执行到getData的时候就不在往下走,而是跳转到下一个vue文件进入queryEchartsData方法,当所有vue文件都进入过queryEchartsData方法后,才会再继续执行getData后面的内容,无语,这个也行不通啊…总归是要解决,最后通过不停的喂ChatGPT,终于是找到了解决办法,使用请求队列和限流,实现一个请求队列,控制并发请求的数量,避免同时发起过多的请求。

qq_34337333的博客 4366

利用多线程和queue实现生产-消费者模式--消息队列

生产者消费者模式也是一种常见的设计模式,而消息队列是较好的实现方式之一,解耦和支持并发,还有其他不同的方式来实现消息队列,后面再继续补充。

cy15625010944的博客 1417

java多线程消息队列的实现

1、定义一个队列缓存池: [code="java"]private static List queueCache = new LinkedList();[/code] 2、定义队列缓冲池最大消息数,如果达到该值,那么队列检入将等待检出低于该值时继续进行。 [code="java"]private Integer offerMaxQueue = 2000;[/code] 3、定义...

lyongq04的博客 1109

什么情况下异步操作使用消息队列而不是多线程

Redis提供了两种方式来作消息队列。 一个是使用生产者消费模式模式,另一个就是发布订阅者模式。 前者会让一个或者多个客户端监听消息队列,一旦消息到达,消费者马上消费,谁先抢到算谁的,如果队列里没有消息,则消费者继续监听;’后者也是一个或多个客户端订阅消息频道,只要发布者发布消息,所有订阅者都能收到消息,订阅者都是平等的。 一、异步处理选择 1.消息队列多线程两者并不冲突,多线程可以作为队列的生产者和消费者。 使用外部的消息队列时,第一是可以提高应用的稳定性,当程序fail后,写入外部消息队列的...

有趣的人生 一半是山川湖海 一半是初心情怀 4054

linux消息队列多线程,基于Linux的消息队列多线程编程实现的聊天室(一)

http://blog.csdn.net/mr_raptor/article/details/8484505本程序主要是针对Linux IPC通信初学者对Linux下消息队列通信机制,多线程编程,字符串处理,链表操作,信号简单处理等基本概念的练习。原理:消息队列是System V支持一种IPC机制,通过类似链表的操作向一个FIFO里通过msgsnd发送用户自定义数据,进程可以通过msgrcv来接收...

weixin_33293848的博客 429

发送邮件要使用消息队列还是多线程

消息队列多线程应该怎么选择呢? 可靠性要求高时选择消息队列消息队列多线程两者并不冲突,多线程可以作为队列的生产者和消费者。 不着急知道结果,尽量使用消息队列,保证服务器的压力减小,因为多线程对cpu的消耗大: 用线程的话,会占用主服务器资源, 消息队列的话, 可以放到其他机器上运行, 让主服务器尽量多的服务其他请求。 需要解耦的时候用消息队列: 解耦更充分,架构更合理 多线程是在编程语言层面解决问题 消息队列是在架构层面解决问题 容易出现线程安全问题或者批量操作时,尽量使用消息队列

qq_41230572的博客 755

多线程】C++自实现适用于多线程的原子消息队列

这些是3年前都自实现的,现在记录起来,以防忘记丢失,以便后续查阅使用。 代码:      xinclude.h文件: #ifndef _XINCLUDE_H_ #define _XINCLUDE_H_ //include #include #include #include #include #include #include #include #inclu

蔚蓝的天空Tom 1749

为什么异步操作使用消息队列而不是多线程

https://blog.csdn.net/ds1130071727/article/details/106602840/

haohaoxuexiyai的博客 727

android多线程

什么时候使用多线程: 1. 耗时操作使用多线程, 耗时操作放在UI线程中会导致用户的操作无法得到响应. 2. 阻塞操作使用多线程, 理由同上. 3. 多核CUP的设备使用多线程, 可以有效提高CPU的利用率. 4. 并行操作使用多线程.   android中的多线程模型主要涉及的类有:Looper, Handler, MessageQueue, Message等.   Lo

478

C++多线程通信

多线程通信与多线程同步很多时候容易被人弄混,本文旨在指出两者区别,同时通过简单示例介绍消息队列

肩上风骋的博客 1753

基于Linux的进程聊天室,基于Linux的消息队列多线程编程实现的聊天室(一)...

本程序主要是针对Linux IPC通信初学者对Linux下消息队列通信机制,多线程编程,字符串处理,链表操作等基本概念的练习。原理:消息队列是System V支持一种IPC机制,通过类似链表的操作向一个FIFO里通过msgsnd发送用户自定义数据,进程可以通过msgrcv来接收指定类似mtype的数据,从而实现进程间通信。主要实现了以下功能:1.通过多个终端登录,不同终端上登录用户实现私聊2.群聊...

weixin_35440082的博客 732

消息队列

在项目之中遇见的,感觉挺实用的,记载下来。 #include <unistd.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h&gt...

lq496387202的博客 226

redis list 实现消息队列 多线程消费

redis list 实现消息队列 多线程消费

qq_17586173的博客 5339
上一篇: 用OWC生成统计分析图
下一篇: 使用Web Service总结
nyzfl
博客等级 码龄21年 10粉丝 14原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值