Транзакционные очереди
50C# и .NET --- Сетевое программирование --- Транзакционные очереди
В случае восстанавливаемых сообщений нет никакой гарантии их доставки в том порядке, в котором они были отправлены, а также в том, что доставка будет однократной. Сбои в сети могут привести к многократной доставке одних и тех же сообщений; это случается и тогда, когда отправитель и получатель имеют несколько установленных протоколов, используемых Message Queuing.
Транзакционные очереди должны применяться, когда необходимы следующие гарантии:
сообщения должны появляться в том порядке, в котором были отправлены;
сообщения должны появляться по одному разу.
В случае транзакционных очередей одна транзакция не охватывает отправку и прием сообщений. Природа Message Queuing такова, что между отправкой и получением сообщения может пройти довольно длительное время. В отличие от этого, транзакции должны быть кратковременными. В Message Queuing первая транзакция используется для отправки сообщения в очередь, вторая — для передачи его по сети и третья — для получения сообщения.
В следующем примере демонстрируется создание транзакционной очереди сообщений, а также отправка сообщения с использованием транзакции. Транзакционная очередь сообщений создается передачей true во втором параметре методу MessageQueue.Create():
using System;
using System.Messaging;
namespace MSMQSample
{
class Program
{
static void Main(string[] args)
{
if (!MessageQueue.Exists(@".\MyTransactionalQueue"))
{
MessageQueue.Create(@".\MyTransactionalQueue", true);
}
var queue = new MessageQueue(@".\MyTransactionalQueue");
var transaction = new MessageQueueTransaction();
try
{
transaction.Begin();
queue.Send("a", transaction);
queue.Send("b", transaction);
queue.Send("c", transaction);
transaction.Commit();
}
catch
{
transaction.Abort();
}
}
}
}
Если в очередь необходимо записывать сразу несколько сообщений в пределах одной транзакции, то для этого придется создать экземпляр объекта MessageQueueTransaction и вызвать его метод Begin(). По завершении отправки всех сообщений, относящихся к транзакции, следует вызвать метод Commit() того же объекта MessageQueueTransaction. Для отмены транзакции (не оставляя никаких сообщений в очереди) должен быть вызван метод Abort(), что и делается в блоке catch.