Microsoft Message Queuing (MSMQ) 是 Windows 內建的訊息中介軟體,支援異步、解耦、可靠傳遞的分散式通訊。雖然現代架構常用 RabbitMQ、Kafka、Azure Service Bus,但 MSMQ 在 Windows 生態內仍具備:零額外部署、事務支援、AD 整合、高可用等優勢。本文系統講解 C# 開發 MSMQ 應用的完整流程:安裝、佇列引用、發送/接收/閱讀訊息、序列化、錯誤處理。
System.Messaging → 勾選| 佇列類型 | 路徑格式 | 範例 |
|---|---|---|
| 公用佇列 | MachineName\QueueName | SERVER01\OrderQueue |
| 私有佇列 | MachineName\Private$\QueueName | .\Private$\OrderQueue |
| 日誌佇列 | MachineName\QueueName\Journal$ | .\OrderQueue\Journal$ |
. 代表本機。兩種引用方式:
// 方式一:建構子指定路徑(佇列必須存在,否則拋出例外)
MessageQueue mq = new MessageQueue(@".\Private$\MyQueue");
// 方式二:屬性設定(可先建立佇列)
MessageQueue mq = new MessageQueue();
mq.Path = @".\Private$\MyQueue";
// 程式化建立佇列(若不存在)
if (!MessageQueue.Exists(@".\Private$\MyQueue")) {
MessageQueue.Create(@".\Private$\MyQueue", transactional: true); // 交易型佇列
}
mq.Send(1000); // 整數
mq.Send("Hello MSMQ!"); // 字串
mq.Send(DateTime.Now); // 日期時間
// 自定義類別(需可序列化)
[Serializable]
public class Order {
public int OrderId { get; set; }
public string Customer { get; set; }
public decimal Amount { get; set; }
}
// 發送物件實例
Order order = new Order { OrderId = 1001, Customer = "Acme Corp", Amount = 999.99m };
mq.Send(order); // 預設 XML 序列化
// 使用 Message 物件控制標籤、優先級、回應佇列等
Message msg = new Message(order);
msg.Label = "NewOrder";
msg.Priority = MessagePriority.High;
msg.ResponseQueue = responseQueue; // 要求回覆
mq.Send(msg);
| 方法 | 行為 | 適用場景 |
|---|---|---|
Receive() | 阻塞等待、取出並移除訊息 | 一般消費者 |
Receive(TimeSpan) | 超時可控制的阻塞接收 | 輪詢、定時處理 |
Peek() | 讀取但不移除訊息 | 監控、審計、預覽 |
ReceiveById(id) / PeekById(id) | 依訊息 ID 精確存取 | 重試、去重 |
// 同步接收(含超時)
Message msg = mq.Receive(new TimeSpan(0, 0, 30)); // 30 秒超時
// 非同步接收(事件驅動)
mq.ReceiveCompleted += (sender, e) => {
MessageQueue q = (MessageQueue)sender;
Message m = q.EndReceive(e.AsyncResult);
ProcessMessage(m);
q.BeginReceive(); // 繼續監聽
};
mq.BeginReceive(); // 啟動非同步接收循環
預設 XmlMessageFormatter 需明確指定目標類型,否則反序列化失敗:
// 設定可接受的類型陣列
string[] types = { "System.String", "MyNamespace.Order, MyAssembly" };
mq.Formatter = new XmlMessageFormatter(types);
// 接收並讀取 Body
Message msg = mq.Receive();
Order order = (Order)msg.Body; // 自動反序列化
Console.WriteLine($"Order {order.OrderId}: {order.Customer} - {order.Amount}");
三大 Formatter 比較:
// 建立交易型佇列
MessageQueue.Create(@".\Private$\TxQueue", true);
// 發送端
using (MessageQueueTransaction tx = new MessageQueueTransaction()) {
tx.Begin();
mq.Send(order, tx);
// 可包含資料庫操作等
tx.Commit(); // 或 tx.Abort()
}
// 接收端
using (MessageQueueTransaction tx = new MessageQueueTransaction()) {
tx.Begin();
Message msg = mq.Receive(tx);
Process((Order)msg.Body);
tx.Commit(); // 處理失敗可 Abort,訊息回佇列
}
TimeToReachQueue、TimeToBeReceived)或投遞失敗 → 進入死信佇列(系統/交易死信佇列)
// 設定佇列 ACL
MessageQueue mq = new MessageQueue(@".\Private$\SecureQueue");
mq.SetPermissions("DOMAIN\Users", MessageQueueAccessRights.SendMessage, AccessControlEntryType.Allow);
mq.SetPermissions("DOMAIN\Admins", MessageQueueAccessRights.FullControl, AccessControlEntryType.Allow);
mq.Close(); // 釋放非受控資源
mq.Dispose(); // 或 using 區塊
mq.GetAllMessages().Length 或 WMI/效能計數器MSMQ 提供了 Windows 原生、企業級的訊息佇列能力。掌握 System.Messaging 命名空間的核心類別(MessageQueue、Message、MessageQueueTransaction、Formatter)、佇列路徑命名規則、同步/非同步接收模式、交易語義、序列化設定,即可構建健壯的分散式 C# 應用。雖然雲原生時代新選項眾多,但 MSMQ 在混合雲、遷移期、純 Windows 環境下仍是極具性價比的選擇。