morzel.net

.net, js, html, arduino, java... no rants or clickbaits.

IBM.WMQ.MQMessage.ReadString i EndOfStreamException

Ostatnio podczas przeróbki programu do komunikacji z WebSphere MQ (v6.0.2.7) zacząłem znajdować w logach wyjątek typu EndOfStreamException. Jako, że kod adaptera był dość złożony chwilę zajęło zanim znalazłem banalną przyczynę problemów ;)

System.IO.EndOfStreamException: Nie można odczytać danych spoza końca
strumienia.
   w System.IO.__Error.EndOfFile()
   w System.IO.BinaryReader.ReadByte()
   w System.IO.BinaryReader.Read7BitEncodedInt()
   w System.IO.BinaryReader.ReadString()
   w IBM.WMQ.MQMessage.ReadString(Int32 length)

Błąd był zgłaszany dlatego, że czasem w dwóch różnych miejscach występowało wywołanie metody ReadString na tym samym obiekcie MQMessage:

string text = message.ReadString(message.MessageLength);

By pozbyć się kłopotu wystarczy dodać jedną linię kodu:

string text = message.ReadString(message.MessageLength);
message.Seek(0);

Skąd problem?
ReadString to metoda odczytująca strumień bajtów i konwertująca go do stringa*. Po poprawnym odczycie całej treści komunikatu znacznik bieżącej pozycji w strumieniu pozostawał na jego końcu, więc następne wywołanie ReadString musiało skończyć się wyjątkiem EndOfStreamException. Dlaczego musiało? ReadString (IBM.WMQ.MQMessage) korzysta w środku z danych przechowywanych w obiekcie typu MemoryStream. Podczas pobierania tekstu, w zależności od właściwości DataLength komunikatu może być wywoływana metoda ReadString z klasy .NET Framework System.IO.BinaryReader. By odczytać tekst musi ona najpierw pobrać jego zakodowaną długość - do tego służy metoda Read7BitEncodedInt widoczna na śladzie stosu. Korzysta ona z kolei z ReadByte, która po natrafieniu na koniec strumienia rzuca omawiany wyjątek.

* Konwersja zachodzi z użyciem właściwości CharacterSet komunikatu (CCSID).

Komentarze (2) -

  • AP

    2011-04-18 15:57:31 | Odpowiedź

    I'm facing same issue. Thank you for this post. I would definitely give it a try. Weird thing is, it happens only on very high load.
    Question: Shouldn't it be before message.readstring(message.messagelength);

    Like:
    message.seek(0);
    message.readstring(message.messagelength);

    ??

  • morzel

    2011-04-18 20:35:09 | Odpowiedź

    You should try to put Seek method call after reading:
    string text = message.ReadString(message.MessageLength);
    message.Seek(0);

    BTW How did you find my post? Polish language probably looks really weird
    to you Smile I have plans to write in English though, but I first need to improve my
    language skills.

Dodaj komentarz

Loading