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).