posts - 2, comments - 0, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

QT多线程异步调用,类似MFC的PostThreadMessage

Posted on 2009-11-01 02:20 bob.shao 阅读(2420) 评论(0)  编辑 收藏 引用 所属分类: QT

QT多线程异步调用,类似MFCPostThreadMessage

Bob.Shao,2009-11-1

MFC中,每个界面线程都会有一个消息队列,通过函数PostThreadMessage,线程之间可以互发消息,由于Post的方式是非阻塞的,因此系统可以表现出很好的性能。这种消息机制是多线程之间异步调用的极佳方式。

笔者最近学习QT4.5.3的时候,想在QT中找到类似于相似的机制,但是暂时没有发现。于是想,没有就创造它。以下描述我如何使QT拥有MFC的消息机制。

MFC的消息机制,其实就是通过每个消息ID对应函数地址来实现的。明白了这个,构造此机制就简单了。首先使用StlPorthash_map建立消息ID与回调函数地址的映射表,之所以用hash_map,是由于其时间复杂度很低,而且不会随着表项的增多而变慢,但会增加内存使用量,在现在内存较大的年代,这个问题不大。

其次,是通过QThread继承,得到一个基类线程,该线程假设命名MsgThd,在该线程中,配备有hash_map,同时再使用StlPortvector建立一个消息队列。重载QThreadrun函数,其中是一个循环,该循环中不停从vector中尝试得到消息,若得到消息ID,则尝试根据此消息ID,从hash_map得到回调函数地址,若回调函数地址有效,则执行该函数。否则,休眠一定时间(比如1ms),然后继续从vector中尝试得到消息,周而复始。此时,凡是从MsgThd继承的线程已经具有消息队列了。

再次,如何使用该MsgThd呢?方法是,凡是需要消息队列的线程,需从MsgThd继承,定义消息ID,定义回调函数,然后把它们放入hash_map中。举例,若线程AB都是从MsgThd继承,若线程A要给线程B发一个异步消息,那么只需要线程A往线程Bvector中放入一个消息即可,若你喜欢的话,这个动作的函数接口可以写成PostThreadMessage。当然,存放消息的vector,须用加锁解锁,因为它极有可能出现线程A与线程B同时访问的情况,在QT中,可以使用互斥量QMutex

以上所说,是实现QT多线程异步调用的第一种方式。

以下所说,第二种方式。这是笔者学习QT几天后发现的J,因为随着对QT的熟悉,接触到越来越多的内容之后,便发现QT本身有这样的机制。

而这种机制存在于函数QApplication::postEvent中,此函数相当于MFCPostThreadMessage。网上有大量关于QT的讯息,但我还没有找到对这个问题讲得较清楚的。我以下解释,不是最清楚的,但说完了,大家就会使用了。

新建一个类,比如MsgThd,继承自QThread,重写run函数,里面就一个函数exec();据说,exec()是消息机制的触发函数。重写event函数,据说,所有事件(Event)都会经过该函数,类似于MFCPreTranslateMessage。(两个“据说”,说明说法仅供参考,笔者也是刚接触几天,莫怪笔者误人子弟。等我把QT源代码看完之后,就没有“据说”了,呵呵。)

假设线程A需要给线程B发消息,在线程A中有代码举例如下:

QEvent* pEvent = new QEvent((QEvent::Type)1234);

QApplication::postEvent( pThread_B, pEvent );

其中1234,是自己定义的,只要大于QT的保留值1024即可。就像你在MFC自定义消息的时候,需要大于WM_USER0x0400)一样。

上面两句的意思是说,线程A产生了一个事件,它发给了线程B

因此线程B中的event函数可能要这样写:

bool Thread_B::event(QEvent * pEvent )

{

    // 截获住自定义的事件

           if ( pEvent->type() == (QEvent::Type)1234 )

           {

                  std::cout<<"这句话替换成你需要调用的函数"<<std::endl;

           }

           return MsgThd::event(pEvent);

}

这就是第二种方式,实现QT多线程异常调用。

 

以上文字仅供参考,请抱着怀疑的态度去看它,欢迎与我讨论J

 


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理