Получать одно и то же сообщение MSMQ дважды? - PullRequest
0 голосов
/ 02 июня 2009

У меня есть система на базе MSMQ с тремя уровнями, которые взаимодействуют друг с другом. Для простоты я буду называть их слоями 1, 2 и 3. Они располагаются так:

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

Таким образом, уровень 1 связывается только с уровнем 2, уровень 3 - только с уровнем 2, а уровень 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 Ответ

2 голосов
/ 02 июня 2009

Проблема решена ... Я полагаю, что однажды я раздам ​​советы по многопоточности, а затем укушу себя нарушением!

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

receiveResult = <queueName>.BeginReceive()

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

...