메시지 대기열 오류 : 메시지를 읽을 수있는 형식을 찾을 수 없습니다.

StackOverflow https://stackoverflow.com/questions/655276

  •  19-08-2019
  •  | 
  •  

문제

다음과 같이 C#의 메시지 대기열에 메시지를 작성하고 있습니다.

queue.Send(new Message("message"));

다음과 같이 메시지를 읽으려고합니다.

Messages messages = queue.GetAllMessages();
foreach(Message m in messages)
{
  String message = m.Body;
  //do something with string
}

그러나 "이 메시지를 읽을 수있는 포머터를 찾을 수 없다"는 오류 메시지가 표시됩니다.

내가 뭘 잘못하고 있죠?

도움이 되었습니까?

해결책

각 메시지에 포피터를 추가하여 문제를 해결했습니다. 대기열에 포피터를 추가하는 것은 작동하지 않았습니다.

Messages messages = queue.GetAllMessages();
foreach(Message m in messages)
{
  m.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });
  String message = m.Body;

  //do something with string
}

다른 팁

또는 사용할 수 있습니다

 message.Formatter =
     new System.Messaging.XmlMessageFormatter(new Type[1] { typeof(string) });

다음과 같이 몸 대신 메시지의 보디 스트림을 읽을 수 있습니다.

StreamReader sr = new StreamReader(m.BodyStream);    
string messageBody = "";    
while (sr.Peek() >= 0) 
{
    messageBody += sr.ReadLine();
}
Message recoverableMessage = new Message();
recoverableMessage.Body = "Sample Recoverable Message";

recoverableMessage.Formatter = new XmlMessageFormatter(new String[] {"System.String,mscorlib" });

MessageQueue myQueue = new MessageQueue(@".\private$\teste");

대기열도 Formatter를 설정해야합니다.

myQueue.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });

직렬화는 메시지 클래스의 신체 속성에 액세스 할 때만 수행되는 것 같습니다. 메시지에 올바른 포맷터를 설정 한 후 신체 속성에 액세스하는 한 정상적으로 작동합니다.

각 메시지에 대해 Formatter를 만들지 않으려면 큐에 Formatter를 설정하고 각 메시지에 대해 (본체 속성에 액세스하기 전에) 대기열의 형성자에서 Formatter 속성을 설정할 수 있습니다.

_queue.Send(new Message() { Formatter = _queue.Formatter, Body = myData } );

var msg = _qeueu.Receive();
msg.Formatter = _queue.Formatter;
var myObject = (MyClass) msg.Body;

여기의 모든 사람들은 솔루션을 제공하는 데 환상적인 일을 해왔 으며이 문제를 직접 싸우고 난 직접 싸움을 마치고 나 자신의 2C를 던져 버리고 제가 생각해 낸 솔루션을 보여주고 싶었습니다.

첫째, 대기열이 만들어지면 나는 그런 권한을 열어야합니다 (응용 프로그램의 맥락에서 큐 보안에 대해 걱정하지 않습니다 ... 이것은 계산 된 결정입니다).

queue.SetPermissions("Everyone", MessageQueueAccessRights.FullControl, AccessControlEntryType.Set);

그 라인이 없으면 모든 종류의 액세스 할 수없는 오류를 받고 컴퓨터 관리 화면에서 큐를 찾아 볼 수 없었습니다. 우연히도 당신에게 일어나고 당신이 단지 액세스 할 수없는 줄을 죽이는 방법이 궁금하다면 :

  1. "메시지 대기 중"서비스 중지
  2. GOTO "C : Windows System32 MSMQ Storage LQS"
  3. 메모장으로 각 파일을 열고 큐 이름을 찾으십시오 (가장 최근에 수정 된 파일 일 가능성이 높습니다).
  4. 해당 파일을 삭제하고 메시징 서비스를 다시 시작하십시오

큐 메시지 항목에 대한 기본 클래스를 만들고 [SERIALIZALE]를 표시하십시오. 애플리케이션로드 캐시에서 다음과 같은 것을 사용하여 모든 메시지 유형의 목록이 있습니다.

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는 실제로 그런 식으로 작업하는 것을 좋아하지 않습니다. 따라서 백그라운드 스레드를 생성하고 메시지를 사용할 수있게되면 큐의 차단 메소드 수신을 호출합니다. 거기에서 메시지를 해독하는 것은 다음과 같이 간단합니다.

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;

그리고 그것은 당신이 멋지게 구현하는 데 필요한 모든 것이되어야합니다, Typeafe MSMQ 통합!

이것은 원격 기계에서 개인 대기열을 읽는 데 도움이되었습니다.

MessageQueue queue = new MessageQueue(@"FormatName:Direct=OS:MACHINENAME\private$\MyQueueName", QueueAccessMode.Peek);

Message msg = queue.Peek();
StreamReader sr = new StreamReader(msg.BodyStream);
string messageBody = sr.ReadToEnd();

이것은 매우 잘 작동합니다.

static readonly XmlMessageFormatter f = new XmlMessageFormatter(new Type[] { typeof(String) });

private void Client()
{
    var messageQueue = new MessageQueue(@".\Private$\SomeTestName");

    foreach (Message message in messageQueue.GetAllMessages())
    {
        message.Formatter = f;
        Console.WriteLine(message.Body);
    }
    messageQueue.Purge();
}

Formatter를 추가하면 내 문제가 해결되었습니다.

 public void ReceiveAsync<T>(MqReceived<T> mqReceived)
    {
        try
        {
            receiveEventHandler = (source, args) =>
            {
                var queue = (MessageQueue)source;
                using (Message msg = queue.EndPeek(args.AsyncResult))
                {
                    XmlMessageFormatter formatter = new XmlMessageFormatter(new Type[] { typeof(T) });
                    msg.Formatter = formatter;
                    queue.ReceiveById(msg.Id);
                    T tMsg = (T)msg.Body;
                    mqReceived(tMsg);

                }
                queue.BeginPeek();
            };

            messageQueu.PeekCompleted += receiveEventHandler;
            messageQueu.BeginPeek();

        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

GitHub에서 샘플 코드 및 MSMQ 라이브러리를 볼 수 있습니다.https://github.com/beyazc/msmqint

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top