消息队列第二篇:MessageQueue实战(课程订单)
本篇一开始就上代码,主要演练MessageQueue的实际应用。用户提交订单(消息发送),系统将订单发送到订单队列(Order Queue)中;订单管理系统(消息接收)端,监听消息队列,收到新的消息就显示在订单列表中,用户可以处理订单。原创(每行代码皆为自己手敲的)
1、提交课程订单

public partial class Form1 : Form
{
// author:fjzhang 2017-08-01
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 提交订单按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSubmit_Click(object sender, EventArgs e)
{
try
{
//实例一个课程订单对象
var order = new CourseOrder();
//订单信息
order.Course = new Course()
{
Title = comboBoxCourse.SelectedItem.ToString()
};
//顾客信息
order.Customer = new Customer()
{
Company = textBoxCompany.Text,
Contact = textBoxContact.Text
};
//实例一个队列对象
using (var queue = new MessageQueue(CourseOrder.CourseOrderQueueName))
{
//实例一个消息对象
using (var message = new System.Messaging.Message(order))
{
//设置优先级
if (checkBoxPriority.CheckState == CheckState.Checked)
{
message.Priority = MessagePriority.High;
}
//设置消息可以恢复
message.Recoverable = true;
//发送消息
queue.Send(order, string.Format("课程订单[{0}]", order.Customer.Company));
}
}
//提示订单提交成功
MessageBox.Show("订单提交成功!", "课程订单", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (MessageQueueException ex)
{
//提示异常信息
MessageBox.Show(ex.Message, "异常提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
2、处理课程订单

/// <summary>
/// 订单处理界面 author:fjzhang 2017-08-01
/// </summary>
public partial class Form1 : Form
{
/// <summary>
/// 订单队列
/// </summary>
private MessageQueue orderQueue;
/// <summary>
/// 构造函数,初始化界面窗体,监听订单队列
/// </summary>
public Form1()
{
InitializeComponent();
//队列名称
string queueName = CourseOrder.CourseOrderQueueName;
//初始化订单队列
orderQueue = new MessageQueue(queueName);
//设置消息类型
orderQueue.Formatter = new XmlMessageFormatter(new Type[] {
typeof(CourseOrder),
typeof(Customer),
typeof(Course)
});
//在未收到订单之前,不启用处理订单按钮
btnProcessOrder.Enabled = false;
//开始监听订单队列
Task t1 = new Task(PeekMessages);
t1.Start();
}
/// <summary>
/// 监听订单队列(如果收到新订单,就在订单列表显示出来)
/// </summary>
private void PeekMessages()
{
//使用消息队列枚举器来显示队列的所有消息
using (MessageEnumerator messagesEnumerator = orderQueue.GetMessageEnumerator2())
{
//检查队列中是否有新消息。如果没有消息,就等待队列的新消息,这里设置等待3小时后才退出。
while (messagesEnumerator.MoveNext(TimeSpan.FromHours(3)))
{
//这里的LaBELIdMapping是我自己定义的,就两字String类型的字段(Id,Label)
var lableId = new LabelIdMapping()
{
Id = messagesEnumerator.Current.Id,
Label = messagesEnumerator.Current.Label
};
//使用主线程执行新增收到订单行
this.Invoke(new EventHandler(delegate
{
AddListItem(lableId);
}));
}
//提示等待3小时还没有新消息进队列
MessageBox.Show("三小时内没有订单", "退出提醒", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
/// <summary>
/// 在订单列表新增一项
/// </summary>
/// <param name="labelIdMapping"></param>
private void AddListItem(LabelIdMapping labelIdMapping)
{
//在listBox控件中新增一行
listBox1.Items.Add(labelIdMapping);
}
/// <summary>
/// 处理订单
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnProcessOrder_Click(object sender, EventArgs e)
{
LabelIdMapping labelId = listBox1.SelectedItem as LabelIdMapping;
var message = orderQueue.ReceiveById(labelId.Id);
listBox1.Items.Remove(labelId);
listBox1.SelectedIndex = -1;
btnProcessOrder.Enabled = false;
textBoxCourse.Text = string.Empty;
textBoxCompany.Text = string.Empty;
textBoxContact.Text = string.Empty;
MessageBox.Show(string.Format("订单[{0}]处理成功", labelId.Label), "订单管理", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
/// <summary>
/// 选中消息列表某一行(订单)执行事件(查看订单详情)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
LabelIdMapping labelId = listBox1.SelectedItem as LabelIdMapping;
if (labelId == null)
return;
orderQueue.MessageReadPropertyFilter.Priority = true;
var message = orderQueue.PeekById(labelId.Id);
CourseOrder order = message.Body as CourseOrder;
if (order != null)
{
textBoxCourse.Text = order.Course.Title;
textBoxCompany.Text = order.Customer.Company;
textBoxContact.Text = order.Customer.Contact;
btnProcessOrder.Enabled = true; if (message.Priority > MessagePriority.Normal)
{
labelPriority.Text = "高优先级";
}
else
{
labelPriority.Text = "--";
}
}
else
{
MessageBox.Show("当前选中的不是课程订单", "订单管理", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
3、效果

以上就是今天实现的全部代码,主要实现了消息的发送和消息的接收,代码写了注释。有不足的地方,上一篇写到消息有几种类型,其中有两种“确认消息”和“响应消息”还没有演示,后面再写一篇应用“确认消息”和“响应消息”。
消息队列第二篇:MessageQueue实战(课程订单)的更多相关文章
- Java中常用的七个阻塞队列第二篇DelayQueue源码介绍
Java中常用的七个阻塞队列第二篇DelayQueue源码介绍 通过前面两篇文章,我们对队列有了了解及已经认识了常用阻塞队列中的三个了.本篇我们继续介绍剩下的几个队列. 本文主要内容:通过源码学习De ...
- 消息队列第一篇:MessageQueue介绍
消息队列有哪些好处或功能: 1.消息可以在断开连接的环境下发送.不需要同时运行正在发送和正在接收的应用程序. 2.使用快捷模式,消息可以非常快地发送.在快捷模式下,消息存储在内存中. 3.对于可恢复的 ...
- RabbitMQ消息队列入门篇(环境配置+Java实例+基础概念)
一.消息队列使用场景或者其好处 消息队列一般是在项目中,将一些无需即时返回且耗时的操作提取出来,进行了异步处理,而这种异步处理的方式大大的节省了服务器的请求响应时间,从而提高了系统的吞吐量. 在项目启 ...
- 消息队列-一篇读懂rabbitmq(生命周期,confirm模式,延迟队列,集群)
什么是消息队列? 就是生产者生产一条消息,发送到这个rabbitmq,消费者连接rabbitmq并且进行消费,生产者和消费者并需要知道对方是如何工作的,从而实现程序之间的解耦,异步和削峰,这也就是消息 ...
- 鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据 | 百篇博客分析OpenHarmony源码 | v33.02
百篇博客系列篇.本篇为: v33.xx 鸿蒙内核源码分析(消息队列篇) | 进程间如何异步传递大数据 | 51.c.h .o 进程通讯相关篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 自旋锁 ...
- 线程安全使用(四) [.NET] 简单接入微信公众号开发:实现自动回复 [C#]C#中字符串的操作 自行实现比dotcore/dotnet更方便更高性能的对象二进制序列化 自已动手做高性能消息队列 自行实现高性能MVC WebAPI 面试题随笔 字符串反转
线程安全使用(四) 这是时隔多年第四篇,主要是因为身在东软受内网限制,好多文章就只好发到东软内部网站,懒的发到外面,现在一点点把在东软写的文章给转移出来. 这里主要讲解下CancellationT ...
- ASP.NET Core消息队列RabbitMQ基础入门实战演练
一.课程介绍 人生苦短,我用.NET Core!消息队列RabbitMQ大家相比都不陌生,本次分享课程阿笨将给大家分享一下在一般项目中99%都会用到的消息队列MQ的一个实战业务运用场景.本次分享课程不 ...
- 跟我一起学WCF(1)——MSMQ消息队列
一.引言 Windows Communication Foundation(WCF)是Microsoft为构建面向服务的应用程序而提供的统一编程模型,该服务模型提供了支持松散耦合和版本管理的序列化功能 ...
- 【MQ】消息队列及常见MQ比较
一.什么是消息队列 我们可以把消息队列比作是一个存放消息的容器,当我们需要使用消息的时候可以取出消息供自己使用.消息队列是分布式系统中重要的组件,使用消息队列主要是为了通过异步处理提高系统性能和削峰. ...
随机推荐
- C语言 基础练习40
一.题目 1.输入2个整数,求两数的平方和并输出. 2. 输入一个圆半径(r)当r>=0时,计算并输出圆的面积和周长,否则,输出提示信息. 3.函数y=f(x)可表示为: 4.编写一个程序,从4 ...
- 洛谷 P1198 [JSOI2008]最大数
洛谷 P1198 [JSOI2008]最大数 题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. ...
- FFM算法解析及Python实现
1. 什么是FFM? 通过引入field的概念,FFM把相同性质的特征归于同一个field,相当于把FM中已经细分的feature再次进行拆分从而进行特征组合的二分类模型. 2. 为什么需要FFM? ...
- c#总结:datatable的方法大全
最近在做一个数据处理,保存到datatable中,在过程中了解了datatable一些用法,总结一下: //定义 DataTable dt = new DataTable(); //写入列名: htT ...
- pycharm字体放大缩小设置
放大设置 File —> settings—> Keymap —>在搜寻框中输入:increase —> Increase Font Size(双击) —> 在弹出的对话 ...
- Lookup 转换组件
查找转换(Lookup)组件用于实现两个数据源的连接,实现的方式是嵌套循环.查找转换通常在内存中缓存查找数据集,然后在输入管道中,把输入数据的每一行都和缓存中的查找数据集进行比较,并输出匹配成功和失败 ...
- 动态加载与插件系统的初步实现(四):解析JSON、扩展Fiddler
按文章结构,这部分应该给出WCFRest项目示例,我想WinForm示例足够详尽了,况且WCFRest还不需要使用插件AppDomain那一套,于是把最近写的Fiddler扩展搬上来吧. Fiddle ...
- 人在囧途——Java程序猿学习Python
引言 LZ之前其实一直对python都很好奇,只是苦于平时没有时间去了解它,因此趁着51假期这个机会,便迫不及待的开始了自己的探索.作为一个标准的Java程序猿,在了解python的过程当中,LZ遇到 ...
- webgl绘制粗线段
webgl1不支持设置线段宽度,这就只好通过shader来实现了,参考了踏得网的例子,引用地址:http://wow.techbrood.com/fiddle/43140.先在此感谢踏得网创始人之一 ...
- 与(&)、或(|)等运算符理解及其特殊用途
1.按位与运算符(&) 在与运算中两个开关是串联的,如果我们要开灯,需要两个开关都打开灯才会打开.理解为A与B都打开,则开灯,所以是1&1=1任意一个开关没打开,都不开灯,所以其他运算 ...