2017-02-13 17 views
2

У меня есть этот тестовый код, который прослушивает сообщения навсегда. Если он получит его, он распечатает его. Я хочу сделать, чтобы не создавать объект MQMessage до каждого get(). Как повторно использовать MQMessage для нескольких вызовов для get()?Повторное использование объекта MQMessage

using System; 
using IBM.WMQ; 

namespace WMQ { 
    class Program { 
     static void Main(string[] args) { 
      string QueueManagerName = "A1PATA00"; 
      string channelName = "ECACHE"; 
      string connectionName = "A1PATA00.WORLDSPAN.COM(1414)"; 
      var queueManager = new MQQueueManager(QueueManagerName, channelName, connectionName); 
      MQQueue get = queueManager.AccessQueue("SPLASH.ECAC.2", MQC.MQOO_INPUT_AS_Q_DEF | MQC.MQGMO_FAIL_IF_QUIESCING); 
      var gmo = new MQGetMessageOptions(); 
      gmo.Options = MQC.MQGMO_FAIL_IF_QUIESCING | MQC.MQGMO_WAIT; 
      gmo.WaitInterval = 10000000;// wait time 
      // var queueMessage = new MQMessage(); <--- i want to do this new once! 
      while (true) { 
       var queueMessage = new MQMessage(); // <-- only works if I do this every time i do a get 
       get.Get(queueMessage, gmo); 
       var strReturn = queueMessage.ReadString(queueMessage.MessageLength); 
       Console.WriteLine(strReturn); 
      } 
     } 
    } 
} 
+0

Какой ужасный API. Это просто прямой порт от PL/1? –

+0

Это точно! – johnnycrash

ответ

0

На странице центра знаний IBM MQ "ClearMessage method" документы следующее:

Этот метод очищает буфер часть данных объекта MQMessage. Любое сообщение Данные в буфере данных теряются, потому что MessageLength, DataLength и DataOffset настроены на ноль.


Часть дескриптора сообщения (MQMD) не затронута; Приложению может потребоваться изменить некоторые поля MQMD, прежде чем повторно использовать объект MQMessage . Чтобы снова установить поля MQMD, используйте New, чтобы заменить объект новым экземпляром.

На странице центра знаний IBM MQ "MQMessage .NET class" документы следующие:

общественного Byte [] MessageId {получить; set;}

Для вызова MQQueue.Get это поле указывает идентификатор сообщения сообщения, которое необходимо получить. Обычно диспетчер очереди возвращает первое сообщение с идентификатором сообщения и идентификатором корреляции , которые соответствуют полям дескриптора сообщения. Разрешить любому идентификатору сообщения соответствовать специальному значению MQC.MQMI_NONE.

общественный байт [] CorrelationId {get; set;}

Для вызова MQQueue.Get будет найден идентификатор корреляции сообщения . Менеджер очереди возвращает первое сообщение с идентификатором сообщения и идентификатором корреляции, который соответствует полям дескриптора . Значение по умолчанию, MQC.MQCI_NONE, помогает любому сопоставимому идентификатору .

Попробуйте это:

  var queueMessage = new MQMessage(); <--- i want to do this new once! 
      while (true) { 
       //var queueMessage = new MQMessage(); // <-- only works if I do this every time i do a get 
       queueMessage.ClearMessage(); 
       queueMessage.MessageId = MQC.MQMI_NONE; 
       queueMessage.CorrelationId = MQC.MQCI_NONE; 
       get.Get(queueMessage, gmo); 
+0

Я уже пробовал это. Просто блокирует Get() навсегда. Вы бы подумали, что это сработает. – johnnycrash

+0

Я только что нашел это при переполнении стека. http://stackoverflow.com/questions/18027043/how-do-i-browse-a-websphere-mq-queue-through-all-messages. Они также очищают идентификатор корреляции. Я собираюсь проверить это. – johnnycrash

+0

yep. queueMessage.MessageId = MQC.MQMI_NONE; queueMessage.CorrelationId = MQC.MQCI_NONE; делает трюк. Положите это в свой ответ и больно дайте его вам. – johnnycrash

2
  1. Когда я вижу подобные вопросы, я качаю головой. Вы не понимаете объектно-ориентированные понятия в .NET VM (framework) и сбор мусора.
  2. Кроме того, почему бы вам не написать чистый код C#?
  3. Наконец, в мире, где безопасность очень важна, ваш код не поддерживает ни SSL/TLS, ни идентификатор пользователя &.

(1) Обратите внимание, где я определяю объект MQMessage (очень важно).

Там в основном не разница в использовании памяти или скорости между следующими 2 фрагменты кода:

(А)

MQMessage msg = null; 
while (true) 
{ 
    msg = new MQMessage(); 
    get.Get(msg, gmo); 
    Console.WriteLine(msg.ReadString(msg.MessageLength)); 
} 

(Б)

MQMessage msg = new MQMessage(); 
while (true) 
{ 
    get.Get(msg, gmo); 
    Console.WriteLine(msg.ReadString(msg.MessageLength)); 
    msg.ClearMessage(); 
    msg.MessageId = MQC.MQMI_NONE; 
    msg.CorrelationId = MQC.MQCI_NONE; 
} 

Я предпочитаю (А) потому что он чище и легче читать.

(2) Когда вы используете «var», вы заставляете платформу .NET угадывать, что вы делаете. Выполняйте чисто объектно-ориентированное программирование. т.е.

MQMessage msg = new MQMessage(); 

(3) Явные установки имени канала и имя соединения в MQQueueManager не позволяет установку информации о безопасности MQ. Кроме того, НЕ используйте класс MQEnvironment, поскольку он НЕ является потокобезопасным. Гораздо лучше разместить всю информацию в Hashtable и передать Hashtable в класс MQQueueManager. Вот пример MQ .NET управляемого режима с использованием Hashtable для MQ информации на соединение:

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Text; 
using IBM.WMQ; 

namespace MQTest02 
{ 
    class MQTest02 
    { 
     private Hashtable inParms = null; 
     private Hashtable qMgrProp = null; 
     private System.String qManager; 
     private System.String outputQName; 

     /* 
     * The constructor 
     */ 
     public MQTest02() 
     : base() 
     { 
     } 

     /// <summary> Make sure the required parameters are present.</summary> 
     /// <returns> true/false 
     /// </returns> 
     private bool allParamsPresent() 
     { 
     bool b = inParms.ContainsKey("-h") && inParms.ContainsKey("-p") && 
        inParms.ContainsKey("-c") && inParms.ContainsKey("-m") && 
        inParms.ContainsKey("-q"); 
     if (b) 
     { 
      try 
      { 
       System.Int32.Parse((System.String)inParms["-p"]); 
      } 
      catch (System.FormatException e) 
      { 
       b = false; 
      } 
     } 

     return b; 
     } 

     /// <summary> Extract the command-line parameters and initialize the MQ variables.</summary> 
     /// <param name="args"> 
     /// </param> 
     /// <throws> IllegalArgumentException </throws> 
     private void init(System.String[] args) 
     { 
     inParms = Hashtable.Synchronized(new Hashtable()); 
     if (args.Length > 0 && (args.Length % 2) == 0) 
     { 
      for (int i = 0; i < args.Length; i += 2) 
      { 
       inParms[args[i]] = args[i + 1]; 
      } 
     } 
     else 
     { 
      throw new System.ArgumentException(); 
     } 

     if (allParamsPresent()) 
     { 
      qManager = ((System.String)inParms["-m"]); 
      outputQName = ((System.String)inParms["-q"]); 

      qMgrProp = new Hashtable(); 
      qMgrProp.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED); 

      qMgrProp.Add(MQC.HOST_NAME_PROPERTY, ((System.String)inParms["-h"])); 
      qMgrProp.Add(MQC.CHANNEL_PROPERTY, ((System.String)inParms["-c"])); 

      try 
      { 
       qMgrProp.Add(MQC.PORT_PROPERTY, System.Int32.Parse((System.String)inParms["-p"])); 
      } 
      catch (System.FormatException e) 
      { 
       qMgrProp.Add(MQC.PORT_PROPERTY, 1414); 
      } 

      if (inParms.ContainsKey("-u")) 
       qMgrProp.Add(MQC.USER_ID_PROPERTY, ((System.String)inParms["-u"])); 

      if (inParms.ContainsKey("-x")) 
       qMgrProp.Add(MQC.PASSWORD_PROPERTY, ((System.String)inParms["-x"])); 

      if (inParms.ContainsKey("-s")) 
       qMgrProp.Add(MQC.SECURITY_EXIT_PROPERTY, ((System.String)inParms["-s"])); 

      System.Console.Out.WriteLine("MQTest02:"); 
      Console.WriteLine(" QMgrName ='{0}'", qManager); 
      Console.WriteLine(" Output QName ='{0}'", outputQName); 

      System.Console.Out.WriteLine("QMgr Property values:"); 
      foreach (DictionaryEntry de in qMgrProp) 
      { 
       Console.WriteLine(" {0} = '{1}'", de.Key, de.Value); 
      } 
     } 
     else 
     { 
      throw new System.ArgumentException(); 
     } 
     } 

     /// <summary> Connect, open queue, read a message, close queue and disconnect. 
     /// 
     /// </summary> 
     /// <throws> MQException </throws> 
     private void testReceive() 
     { 
     MQQueueManager qMgr = null; 
     MQQueue queue = null; 
     int openOptions = MQC.MQOO_INPUT_AS_Q_DEF + MQC.MQOO_FAIL_IF_QUIESCING; 
     MQGetMessageOptions gmo = new MQGetMessageOptions(); 
     MQMessage receiveMsg = null; 

     try 
     { 
      qMgr = new MQQueueManager(qManager, qMgrProp); 
      System.Console.Out.WriteLine("MQTest02 successfully connected to " + qManager); 

      queue = qMgr.AccessQueue(outputQName, openOptions, null, null, null); // no alternate user id 
      System.Console.Out.WriteLine("MQTest02 successfully opened " + outputQName); 

      receiveMsg = new MQMessage(); 

      queue.Get(receiveMsg, gmo); 
      System.Console.Out.WriteLine("Message Data>>>" + receiveMsg.ReadString(receiveMsg.MessageLength)); 
     } 
     catch (MQException mqex) 
     { 
      System.Console.Out.WriteLine("MQTest02 cc=" + mqex.CompletionCode + " : rc=" + mqex.ReasonCode); 
     } 
     catch (System.IO.IOException ioex) 
     { 
      System.Console.Out.WriteLine("MQTest02 ioex=" + ioex); 
     } 
     finally 
     { 
      try 
      { 
       queue.Close(); 
       System.Console.Out.WriteLine("MQTest02 closed: " + outputQName); 
      } 
      catch (MQException mqex) 
      { 
       System.Console.Out.WriteLine("MQTest02 cc=" + mqex.CompletionCode + " : rc=" + mqex.ReasonCode); 
      } 
      try 
      { 
       qMgr.Disconnect(); 
       System.Console.Out.WriteLine("MQTest02 disconnected from " + qManager); 
      } 
      catch (MQException mqex) 
      { 
       System.Console.Out.WriteLine("MQTest02 cc=" + mqex.CompletionCode + " : rc=" + mqex.ReasonCode); 
      } 
     } 
     } 

     /// <summary> main line</summary> 
     /// <param name="args"> 
     /// </param> 
     //  [STAThread] 
     public static void Main(System.String[] args) 
     { 
     MQTest02 mqt = new MQTest02(); 

     try 
     { 
      mqt.init(args); 
      mqt.testReceive(); 
     } 
     catch (System.ArgumentException e) 
     { 
      System.Console.Out.WriteLine("Usage: MQTest02 -h host -p port -c channel -m QueueManagerName -q QueueName [-u userID] [-x passwd] [-s securityExit]"); 
      System.Environment.Exit(1); 
     } 
     catch (MQException e) 
     { 
      System.Console.Out.WriteLine(e); 
      System.Environment.Exit(1); 
     } 

     System.Environment.Exit(0); 
     } 
    } 
} 

Чтобы запустить MQTest02 используя информацию, это было бы:

MQTest02.exe -h A1PATA00.WORLDSPAN.COM -p 1414 -m A1PATA00 -c ECACHE -q SPLASH.ECAC.2 
+0

Многопоточное преимущество, подразумеваемое этим ответом, является важной деталью в отношении того, почему метод A лучше метода B. Объект, созданный в образце A, может передаваться потоку, в то время как следующий экземпляр сообщения передается в другой поток. В образце B ClearMessages вам необходимо полностью обработать это сообщение до повторного использования. –

Смежные вопросы