2009-06-02 2 views
0

У меня есть система на базе MSMQ с тремя слоями, которые общаются друг с другом. Ради простоты я буду ссылаться на них как Layer 1, 2 и 3. Они сидят, как это:Получает одно и то же сообщение MSMQ дважды?

Layer 1 <-> Layer 2 <-> Layer 3 

Так Layer 1 переговоры только Layer 2, Layer 3 говорит только Layer 2, а второй уровень - для обоих. У меня есть четыре очереди для этого,

Layer1_in 
Layer1_out 
Layer3_out 
Layer3_in 

И слои взаимодействуют через эту инфраструктуру:

Layer 1 -> Layer1_out -> Layer 2 
Layer 1 <- Layer1_in <- Layer 2 
Layer 3 -> Layer3_out -> Layer 2 
Layer 3 <- Layer3_in <- Layer 2 

(извините, если это более исчерпывающим, чем это необходимо)

Во всяком случае, сообщение получает передается от Слой 1 до уровня 2 выполняется некоторая обработка, затем другое (связанное) сообщение отправляется на уровень 3 и наоборот. Проблема, с которой я сталкиваюсь, заключается в том, что иногда у меня есть два сообщения, отправленные с уровня 1 на уровень 2, но вместо того, чтобы получать оба сообщения, чтобы оно получало первое сообщение дважды. Я использую BeginReceive по адресу Layer1_out, чтобы асинхронно получать сообщение. Когда это завершает, я обрабатываю полученное сообщение и снова вызываю BeginReceive, чтобы получить следующее сообщение.

Чтобы отслеживать это, я внедрил счетчик сообщений на отправляющей стороне, и я напишу его в текстовый файл. Я использую свойство Extension для хранения строкового представления этого номера сообщения, чтобы затем получить номер сообщения на стороне обработки. Когда я получаю сообщение, я беру этот номер и записываю его в другой файл. Это должно производить два файла, которые имеют то же содержание, но вместо этого я буду видеть вещи, как

00000000000000000214 
00000000000000000215 
00000000000000000215 <- this is bad! 
00000000000000000217 
00000000000000000218 
00000000000000000219 

В журнале квитанции, с указанием, что сообщение 215 был обработан дважды, и 216 не пришел до конца. Для моих целей это не влияет ни на что для меня, чтобы обрабатывать одно и то же сообщение дважды (отсюда почему это не замедлило в течение некоторого времени), но отсутствие сообщения вообще является большой проблемой.

Любые мысли?

+1

Звучит подозрительно, как недавнее сообщение Раймонда Чена http://blogs.msdn.com/oldnewthing/archive/2009/05/22/9634511.aspx – Ant

+0

@Ant: Интересное чтение, но я не знаю, что он много влияют на эту проблему, поскольку я не выполняю никакой явной синхронизации потоков сам (может быть что-то сделано под капотом в библиотеках MSMQ, но у меня нет контроля или знания об этом). Возможно, я что-то пропустил, хотя ... у вас есть идея, как это применимо? –

+0

Есть ли у вас несколько потоков, отправляющих/получающих данные с обеих сторон? Возможно, один поток перезаписывает данные другого потока. –

ответ

2

Проблема решена ... цифры, которые я бы посоветовал многопользовательским советом в один прекрасный день, а затем укусил себя нарушением себя!

Виновником была эта линия:

receiveResult = <queueName>.BeginReceive() 

Когда я был еще одно сообщение уже ждут в очереди, мой ReceiveCompleted событие стреляла в другом потоке и получить к моему EndReceive(receiveResult) вызова до возвращаемого значения из BeginReceive было фактически записанный в переменную receiveResult. В результате я звонил EndReceive с тем же значением и снова получал то же сообщение! Блокировка всего обработчика событий вокруг объекта синхронизации позаботилась об этой проблеме.

+1

- переменная 'receiveResult' была разделена между всеми потоками? почему вы не используете [AsyncResult] (http://msdn.microsoft.com/en-us/library/system.messaging.receivecompletedeventargs.asyncresult.aspx) в [ReceiveCompleted] (http://msdn.microsoft.com). /en-us/library/system.messaging.messagequeue.receivecompleted.aspx) аргументы события для завершения приема? – Boo

Смежные вопросы