【问题标题】:Starting multiple threads in a for loop as no effect在 for 循环中启动多个线程无效
【发布时间】:2015-09-30 02:25:47
【问题描述】:

我正在尝试从 websphere mq 队列中读取消息并将其转储到另一个队列中。

下面是我必须做的代码

private void transferMessages()
{
    MQQueueManager sqmgr = connectToQueueManager(S_SERVER_NAME, S_QMGR_NAME, S_PORT_NUMBER, S_CHANNEL_NAME);
    MQQueueManager dqmgr = connectToQueueManager(D_SERVER_NAME, D_QMGR_NAME, D_PORT_NUMBER, D_CHANNEL_NAME);
    if (sqmgr != null && dqmgr != null)
    {
        MQQueue sq = openSourceQueueToGet(sqmgr, S_QUEUE_NAME);
        MQQueue dq = openDestQueueToPut(dqmgr, D_QUEUE_NAME);
        if (sq != null && dq != null)
        {
            setPutMessageOptions();
            setGetMessageOptions();
            processMessages(sqmgr, sq, dqmgr, dq);
        }
    }
}

我在 for 循环中调用上述方法并创建单独的线程,如下所示。

int NO_OF_THREADS = 5;
Thread[] ts = new Thread[NO_OF_THREADS];
for (int i = 0; i < NO_OF_THREADS; i++)
{ 
    ts[i] = new Thread(() => transferMessages());
    ts[i].Start();        
}

如您所见,我正在 transferMessages 方法中与队列管理器建立新连接。由于某种原因不确定,该程序仅与 MQ 建立一个连接。

连接队列管理器的自定义方法如下..

    private MQQueueManager connectToQueueManager(string MQServerName, string MQQueueManagerName, string MQPortNumber, string MQChannel)
    {
        try
        {
            mqErrorString = "";
            MQQueueManager qmgr;
            Hashtable mqProps = new Hashtable();
            mqProps.Add(MQC.HOST_NAME_PROPERTY, MQServerName);
            mqProps.Add(MQC.CHANNEL_PROPERTY, MQChannel);
            mqProps.Add(MQC.PORT_PROPERTY, Convert.ToInt32(MQPortNumber));
            mqProps.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_CLIENT);
            qmgr = new MQQueueManager(MQQueueManagerName, mqProps);
            return qmgr;
        }
        catch (MQException mqex)
        {
            //catch and log MQException here
            return null;
        }
    }

任何建议我错过了什么?

【问题讨论】:

  • 链中的某些东西正在序列化连接调用。在您自己的 connectToQueueManager 或 MQ API 中。无论如何你都不应该使用线程(查看任务和线程池)。
  • @Henk,我添加了自定义 connectToQueueManager 方法代码。除了通过使用 HashTable 来存储连接属性并使用与标准 MQ API 建立与 MQ 队列管理器的连接来创建与队列管理器的连接之外,它没有任何其他功能。另外,根据您的建议,我我会检查任务或线程池。一旦我找到解决我面临的问题的方法,我会更新。谢谢。
  • 如果您的应用程序连接同一组队列管理器,那么为什么不只连接和打开一次队列!
  • @Shashi,我想通过与队列管理器建立多个连接并打开队列的多个读写器,以更快的速度从队列中读取消息。

标签: c# multithreading ibm-mq mq


【解决方案1】:

这是因为 MQ 的 Shared Conversation (SHARECNV) 特性,其中从一个应用程序到队列管理器的多个连接共享同一个套接字。该值是客户端和队列管理器在建立连接时协商的值。默认情况下,一个套接字将共享 10 个连接。

您可以将应用程序中的线程数增加到 11,然后您可以看到第二个连接正在打开。有关 SHARECNV 的更多详细信息,请联系here

更新 为 put 和 get 运行 6 个线程时的通道状态。注意我正在连接到同一个队列管理器(仅用于测试目的)。 SHARECNV 设置为 10。

     2 : dis chstatus(MY.SVRCONN)
AMQ8417: Display Channel Status details.
   CHANNEL(MY.SVRCONN)                     CHLTYPE(SVRCONN)
   CONNAME(127.0.0.1)                      CURRENT
   STATUS(RUNNING)                         SUBSTATE(RECEIVE)
AMQ8417: Display Channel Status details.
   CHANNEL(MY.SVRCONN)                     CHLTYPE(SVRCONN)
   CONNAME(127.0.0.1)                      CURRENT
   STATUS(RUNNING)                         SUBSTATE(RECEIVE)

每个运行 5 个线程时。

 3 : dis chstatus(MY.SVRCONN)
AMQ8417: Display Channel Status details.
   CHANNEL(MY.SVRCONN)                     CHLTYPE(SVRCONN)
   CONNAME(127.0.0.1)                      CURRENT
   STATUS(RUNNING)                         SUBSTATE(RECEIVE)

【讨论】:

  • 在这里发布我的问题之前,我尝试将其更改为 0 和其他不同的值。没有运气。
  • 运行您的测试程序并将结果发布为 UPDATE。
  • 能否请您在启动程序之前和之后发布队列管理器连接? (DIS QMSTATUS CONNS) 以及队列 IPPROCS 和 OPPROCS?你是说上面的代码有效,我必须对 MQ 配置/队列管理器配置进行一些更改? PS:我运行了另一个程序,它成功地与队列管理器建立了多个连接。当我现在运行它时,它失败了。尝试使用其他队列管理器进行测试。谢谢。
  • 修改了您的代码以建立连接,删除了打开队列的代码。所以没有 IPPROCS/OPPROCS 详细信息。程序启动前后的连接数分别为22和32。
  • 请记住使用 DISPLAY CONN 命令,该命令将显示与队列管理器建立的连接数,即使它们在一个通道上共享(因此 DISPLAY CHSTATUS 将只显示一个连接)。这将帮助您确定是否进行了多个连接。
猜你喜欢
  • 2017-03-27
  • 1970-01-01
  • 2023-03-03
  • 2021-01-14
  • 1970-01-01
  • 1970-01-01
  • 2011-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多