2012-08-06 30 views
2

我正在使用WebSphere MQ v7服務器和WebSphere MQ Client v7.5以及amqmdnet.dll 7.5.0.0作爲用於通過WebSphere MQ進行通信的.NET庫。有時當我嘗試從隊列中讀取MQMessage時,我得到MQExceptionMQRC_RFH_FORMAT_ERROR的原因。在.NET中接收WebSphere MQ消息WMQ API有時會拋出MQRC_RFH_FORMAT_ERROR

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

此行爲似乎取決於郵件的發件人及其內容。它通常不適用於使用float或double屬性發送消息的不同平臺上的系統。

回答

3

這是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 

反編譯MQMarshalMessageForGet.NET Reflector表明這一點:

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