MSMQ队列学习记录

微软消息队列-MicroSoft Message Queue(MSMQ)

使用感受:简单。

一、windows安装MSMQ服务

控制面板->控制面板->所有控制面板项->程序和功能->选中安装

然后可在计算机管理-->服务和应用程序->消息队列查看队列信息

二、C#中使用MSMQ

使用MessageQueue类操作MSMQ,其在System.Messaging命名空间下,需要添加引用

定义的接口

public interface IMessageSender<T> : IDisposable
{
    /// <summary>
    ///     发送消息
    /// </summary>
    /// <param name="message">消息对象</param>
    void SendMessage(T message);

    void SendMessages(List<T> message);

    /// <summary>
    ///     发送消息
    /// </summary>
    /// <param name="message">消息对象</param>
    /// <param name="label">消息标签</param>
    void SendMessage(T message, string label);
}

接口实现

/// <summary>
///     消息队列对象,由MQueueFactory创建指定路径的队列对象,可发送或批量接收消息。
/// </summary>
/// <typeparam name="T">消息队列存储的消息对象类型</typeparam>
public sealed class MQueue<T> : IDisposable, IMessageSender<T>, IMessageReceiver<T>
{
    public MQueue(MessageQueue mq, string user = "Everyone")
    {
        InnerQueue = mq;
        InnerQueue.Formatter = new XmlMessageFormatter(new[] { typeof(T) });

        InnerQueue.SetPermissions(user ?? "Everyone",
            MessageQueueAccessRights.GenericRead | MessageQueueAccessRights.DeleteMessage |
            MessageQueueAccessRights.DeleteQueue | MessageQueueAccessRights.DeleteJournalMessage);
    }
    #region IMessageSender
    /// <summary>
    ///     内部消息队列对象
    /// </summary>
    private MessageQueue InnerQueue { get; set; }

    /// <summary>
    ///     发送消息
    /// </summary>
    /// <param name="message">消息对象</param>
    public void SendMessage(T message)
    {
        InnerQueue.Send(message);
    }

    public void SendMessages(List<T> message)
    {
        foreach (var item in message)
        {
            InnerQueue.Send(item);
        }
    }

    /// <summary>
    ///     发送消息
    /// </summary>
    /// <param name="message">消息对象</param>
    /// <param name="label">消息标签</param>
    public void SendMessage(T message, string label)
    {
        try
        {
            InnerQueue.Send(message, label);
        }
        catch (Exception ex)
        {
            var path = InnerQueue.Path;
            InnerQueue = new MessageQueue(path);
        }
    }
    #endregion 

    #region IMessageReceiver
    /// <summary>
    /// 获取队列中所有消息
    /// </summary>
    /// <typeparam name="T">消息类型</typeparam>
    /// <param name="exTarget">异常时触发</param>
    /// <returns></returns>
    public List<T> GetAllMessages<T>(MQExceptionTarget exTarget = null)
    {
        return GetMessagesByNum<T>(null, exTarget);
    }
    /// <summary>
    /// 获取队列中指定数量消息
    /// </summary>
    /// <typeparam name="T">消息类型</typeparam>
    /// <param name="num">一次最多取num条数据,默认取所有数据</param>
    /// <param name="exTarget">异常委托</param>
    /// <returns></returns>
    public List<T> GetMessagesByNum<T>(int? num = null, MQExceptionTarget exTarget = null)
    {
        var list = new List<T>();
        if (num.HasValue && num <= 0)
        {
            return list;
        }
        MessageEnumerator enumerator = InnerQueue.GetMessageEnumerator2();
        while (enumerator.MoveNext())
        {
            Message msg = enumerator.RemoveCurrent();
            enumerator.Reset();
            if (msg != null)
            {
                try
                {
                    list.Add((T)msg.Body);
                    if (num.HasValue && list.Count >= num)
                    {
                        break;
                    }
                }
                catch (Exception ex)
                {
                    if (exTarget != null)
                        exTarget(ex);
                }
            }
        }
        return list;
    }
    #endregion

    public void Dispose()
    {
        if (InnerQueue != null)
        {
            InnerQueue.Dispose();
        }
    }
}

建立队列工厂

/// <summary>
///  消息队列工厂,通过指定路径创建或获取相应队列对象
/// </summary>
public class MQueueFactory
{
    /// <summary>
    ///     默认队列路径,在未指定路径的情况下,将创建并返回该路径的消息队列对象
    /// </summary>
    private const string DefaultPath = @".\private$\myQueue";

    /// <summary>
    ///     创建默认路径的消息队列对象
    /// </summary>
    /// <typeparam name="T">消息队列存储的消息对象类型</typeparam>
    /// <returns></returns>
    public static MQueue<T> Create<T>()
    {
        return Create<T>(DefaultPath);
    }

    /// <summary>
    ///     创建指定路径的消息队列路径
    /// </summary>
    /// <typeparam name="T">消息队列存储的消息对象类型</typeparam>
    /// <param name="connStr">指定的消息队列链接字符串 def:".\private$\myQueue"</param>
    /// <param name="autoCreate">不存在则创建队列 远程地址不能创建</param>
    /// <param name="user">获得队列额外权限的个人、组或计算机</param>
    /// <param name="cacheKey">web中Cache键值</param>
    /// <returns></returns>
    public static MQueue<T> Create<T>(string connStr=@".\private$\myQueue", bool autoCreate = false, string user = "Everyone", string cacheKey = "MQCache")
    {
        string path = connStr ?? DefaultPath;
        HttpContext httpContext = HttpContext.Current;
        if (autoCreate && !MessageQueue.Exists(path))
        {
            MessageQueue.Create(path);
        }
        var mq = new MessageQueue(path);
        if (httpContext != null)
        {
            string key = "MQueue" + typeof(T).Name + cacheKey;
            if ((httpContext.Cache[key] == null))
            {
                httpContext.Cache[key] = new MQueue<T>(mq);
            }
            return httpContext.Cache[key] as MQueue<T>;
        }
        return new MQueue<T>(mq,user);
    }
}

写入队列

MQueueFactory.Create<string>(@".\private$\myQueue", autoCreate: true).SendMessage("我是写入的数据~~~");

获取消息

MQueueFactory.Create<string>(@".\private$\myQueue").GetAllMessages<string>();

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏友弟技术工作室

Beego Controllercontroller 逻辑控制器介绍Controller中数据参数处理获取参数

controller就是处理具体的逻辑的,router将请求分发到指定的controlller,controller处理请求,然后返回。 首先我们还是从源码分...

2932
来自专栏LanceToBigData

JavaWeb(一)Servlet中的request与response

一、HttpServletRequest概述 1.1、HttpServletRequest简介   HttpServletRequest对象代表客户端的请求,当...

2828
来自专栏我的小碗汤

来看三个问题

是否允许在HTTP请求时,返回原始请求体数据字节,默认为false(GET or HEAD or 上传文件请求除外)。

1061
来自专栏SDNLAB

SDN开发笔记(七):L2switch源码分析(上)

前言 一般按照odl官方文档或者wiki安装L2switch组件会采用在karaf控制台上输入feature:install odl-l2switch-all命...

4088
来自专栏jeremy的技术点滴

Retrying_Library_For_Java

3265
来自专栏技术博客

Asp.Net Web API 2第七课——Web API异常处理

阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.h...

913
来自专栏博客园

Asp.Net Web API(二)

当然,你也可以创建一个Web API项目,利用 Web API模板,Web API模板使用 ASP.Net MVC提供API的帮助页。

1581
来自专栏MasiMaro 的技术博文

windows 线程

在windows中进程只是一个容器,用于装载系统资源,它并不执行代码,它是系统资源分配的最小单元,而在进程中执行代码的是线程,线程是轻量级的进程,是代码执行的最...

1482
来自专栏无题

线程安全与锁优化——深入理解JVM阅读笔记

我根据我的理解把一些关键的要点整理了出来,并对其中一些内容作了删改。 参考地址:http://www.cnblogs.com/pacoson/p/5351355...

3595
来自专栏Golang语言社区

Golang构建HTTP服务(一)--- net/http库源码笔记

实现一个最简单HTTP server需要多少代码?只需要一行,Python2的python -m SimpleHTTPServer,ruby的ruby -run...

5895

扫码关注云+社区

领取腾讯云代金券