Все здесь проделали фантастическую работу по поиску решений, и, только что закончив борьбу с этой проблемой самостоятельно, я хотел добавить свой собственный 2c и показать решение, которое я нашел, которое работает очень хорошо.
Во-первых, когда создается очередь, я удостоверяюсь, что открываю разрешения примерно так (меня не волнует безопасность очереди в контексте нашего приложения ... это расчетное решение):
queue.SetPermissions("Everyone", MessageQueueAccessRights.FullControl, AccessControlEntryType.Set);
Без этой строки я получал бы всевозможные недоступные ошибки и даже не мог просматривать очередь с экрана управления компьютером. Кстати, если это случится с вами, и вы задаетесь вопросом, как убить очередь, к которой у вас нет доступа, просто:
- Остановить услугу «Очередь сообщений»
- Перейти к "C: \ Windows \ System32 \ msmq \ storage \ lqs"
- Откройте каждый файл в блокноте и найдите имя своей очереди (это, скорее всего, будет файл, который был изменен последним)
- Удалите этот файл и перезапустите службу обмена сообщениями
Создайте базовый класс для элементов сообщений в очереди и отметьте его [Сериализуемый].
При загрузке приложения кешируйте список всех ваших типов сообщений, используя что-то вроде этого:
var types = typeof(QueueItemBase).Assembly
.GetTypes()
.Where(t => typeof(QueueItemBase).IsAssignableFrom(t) && t.IsAbstract == false)
.ToArray();
...
// Create and cache a message formatter instance
_messageFormatter = new XmlMessageFormatter(types);
Теперь вы готовы начать получать сообщения. Моим первым инстинктом было опросить сообщения, но API не очень нравится работать таким образом. Поэтому я создаю фоновый поток и вызываю блокирующий метод Receive в очереди, который вернется, как только сообщение станет доступным. Оттуда декодирование сообщения так же просто, как:
var message = queue.Receive();
if (message == null)
continue;
// Tell the message about our formatter containing all our message types before we
// try and deserialise
message.Formatter = _messageFormatter;
var item = message.Body as QueueItemBase;
И это все, что вам нужно для правильной реализации, безопасной интеграции с MSMQ!