【问题标题】:Receiving WebSphere MQ message in .NET WMQ API sometimes throws MQRC_RFH_FORMAT_ERROR在 .NET WMQ API 中接收 WebSphere MQ 消息有时会抛出 MQRC_RFH_FORMAT_ERROR
【发布时间】:2012-08-06 13:28:46
【问题描述】:

我使用带有 amqmdnet.dll 7.5.0.0 的 WebSphere MQ v7 Server 和 WebSphere MQ Client v7.5 作为 .NET 库,用于通过 WebSphere MQ 进行通信。有时当我尝试从队列中读取MQMessage 时,我得到MQExceptionMQRC_RFH_FORMAT_ERROR 原因。

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

这种行为似乎取决于消息的发送者及其内容。它通常不适用于不同平台上的系统发送具有浮点或双属性的消息。

【问题讨论】:

    标签: c# .net ibm-mq


    【解决方案1】:

    这是 IBM amqmdnet.dll 中的一个全球化错误。在客户端 (strmqtrc.exe) 上打开 MQ 跟踪后,我尝试再次接收消息,并在其中一个跟踪文件中找到:

    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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-10
      • 1970-01-01
      • 2016-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多