2

WebSphereMQを介して通信するための.NETライブラリとしてamqmdnet.dll7.5.0.0を備えたWebSphereMQv7サーバーとWebSphereMQクライアントv7.5を使用しています。時々MQMessage、キューから読み込もうとするMQExceptionと、MQRC_RFH_FORMAT_ERROR理由があります。

var message = new MQMessage();
queue.Get(message);

この動作は、メッセージの送信者とその内容に依存しているようです。通常、floatまたはdoubleプロパティを持つメッセージを送信する異なるプラットフォーム上のシステムでは機能しません。

4

1 に答える 1

3

これは、IBMのamqmdnet.dllのグローバリゼーションのバグです。クライアントでMQトレースをオンにした後(strmqtrc.exe)メッセージを再度受信しようとしましたが、トレースファイルの1つでこれを見つけました。

00001F21 11:48:00.351013   7104.1           :       Exception received
System.FormatException
Message: Input string was not in a correct format.
StackTrace:
   at System.Number.ParseSingle(String value, NumberStyles options, NumberFormatInfo numfmt)
   at System.Convert.ToSingle(String value)
   at IBM.WMQ.MQMarshalMessageForGet.GetValueAsObject(String dt, String propValue)
   at IBM.WMQ.MQMarshalMessageForGet.ProcessAllAvailableRFHs()
00001F22 11:48:00.351115   7104.1           :       We are not sucessful in parsing one of theRFH2Header.Raise the RFH_FORMAT exception and breakfurther processing in loop
00001F23 11:48:00.351825   7104.1           :       MQException CompCode: 2 Reason: 2421

.NET Reflectorを使用した逆コンパイルMQMarshalMessageForGetでは、次のことがわかりました。

private object GetValueAsObject(string dt, string propValue)
{
    ...

    switch (dt)
    {
        ...

        case "r4":
            return Convert.ToSingle(propValue);

        case "r8":
            return Convert.ToDouble(propValue);

        ...
    }

    ...
}

メッセージは、トランスポートの期待されるカルチャではなく、現在のシステムのカルチャで読み取られます(すべてのプラットフォームで同じである必要があります)。問題を再現するための簡単なテスト:

[Test]
public void PutAndGetMessageWithFloatProperty() {
    using (MQQueue queue = _queueManager.AccessQueue(TestQueue, MQC.MQOO_OUTPUT | MQC.MQOO_INPUT_AS_Q_DEF))
    {
        Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");

        MQMessage message = new MQMessage();
        message.SetFloatProperty("TEST_SINGLE", 14.879f);
        message.WriteString("some string");
        message.Format = MQC.MQFMT_STRING;

        queue.Put(message); // Writes property value as 14.879

        Thread.CurrentThread.CurrentCulture = new CultureInfo("cs-CZ");

        MQMessage readMessage = new MQMessage();
        queue.Get(readMessage); // Throws MQException because 14,879 is correct format

        queue.Close();
    }
}

回避策

私はこの単純なスコープクラスを使用しています:

public class CultureForThreadScope : IDisposable {
    private readonly CultureInfo oldCulture;

    public CultureForThreadScope(CultureInfo culture) {
        oldCulture = Thread.CurrentThread.CurrentCulture;
        Thread.CurrentThread.CurrentCulture = culture;
    }

    public void Dispose() {
        Thread.CurrentThread.CurrentCulture = oldCulture;
    }
}

Getそして、スコープへのすべての呼び出しをラップしています。

using (new CultureForThreadScope(CultureInfo.InvariantCulture)) {
    destination.Get(message, getOptions);
}
于 2012-08-06T13:28:46.267 に答える