当前位置: 代码迷 >> QT开发 >> qt如何使用win thread实现多线程通信
  详细解决方案

qt如何使用win thread实现多线程通信

热度:53   发布时间:2016-04-25 03:19:48.0
qt怎么使用win thread实现多线程通信?
近来做socket网络编程,在服务器端需要开个线程循环接收客户的数据。
由于我希望练习使用win thread(windows的线程函数),不想直接使用qt的库类,但是怎么都实现不了进程间的通信。之前看到的子线程与主线程通信都是使用signal-slots,但是换用win thread就不行了。因为win thread限定的线程函数中无法emit signal。

signals:
    void dataReady(int num);

线程函数有两种写法:
一种是定义为普通的函数:DWORD WINAPI threadInit(LPVOID lpParamter);
一种是定义为static member function:DWORD WINAPI Widget::threadInit(LPVOID lpParamter); // 定义为static就可以被线程调用了,否则不行。
使用这两种写法都试过,无论怎么样都无法emit signal。

定义为普通函数
DWORD WINAPI threadInit(LPVOID lpParamter)
{
    int i = 10;
    while (i-- > 0)
    {
        qDebug() << i;
        emit dataReady(i);      // 错误:C3861: 'dataReady': identifier not found
    }

    return 0;
}


定义为static成员函数:
DWORD WINAPI Widget::threadInit(LPVOID lpParamter)
{
    int i = 10;
    while (i-- > 0)
    {
        qDebug() << i;
        emit dataReady(i);   // 错误:C2352: 'Widget::dataReady' : illegal call of non-static member function
    }

    return 0;
}


这两个错误都比较好理解,可以解释清楚。那么,我应该如何使用win thread在qt下实现多线程的通信呢?
另, 我使用的版本是qt 4.8.4。
------解决方案--------------------
首先,你要分清:你那个dataReady到底是谁的成员函数,你又是如何调用其他类的成员函数的?

其次,你要明白:Qt的线程间通讯之所以可以通过(queue方式)信号槽进行通讯,其原因在于,Qt的事件系统是线程安全的。而你自己写的线程内连基本Qt的事件循环系统都无法启动,所以不要鲁莽地使用信号槽进行通讯的。

再次,你要清楚,QWidget及其派生类,都不是线程安全的,所以如果你的dataReady是他们的信号,你是不应该在次线程使用的。

注意:如果你:
1. 直接用系统线程API,而非QtAPI
2. 对Qt事件系统没有透彻的理解(也是不明白queue方式信号槽)

那么你最好不要碰,跨线程的信号槽。(因为即使在使用QThread的情况下,非常非常多的用户都不能正确使用跨线程的信号槽)
------解决方案--------------------
你直接使用Windows API, 在一个全局函数里当然是没有办法直接使用信号、槽的。(信号、槽都需要QObject支持)
你既然在练习Windows API,那就使用Windows的线程相关的同步、互斥(EnterCriticalSection, Event之类的)

使用QThread的时候用Qt的信号槽

在Win32下QThread并不复杂,你可以很容易看到源码是如何调用Windows API的,就和你现在做的一样。
------解决方案--------------------
引用:
Quote: 引用:

使用posix标准的线程函数吧
编译的时候记得加上 -lpthread

额,我觉得这种做法也还是不行。因为用qt做界面显示就必须要和qt打交道,如果用非qt的线程(win/ posix),那估计就完全脱离qt了。qt的信号槽机制是肯定不能再使用了,这么做界面就难度太大了

没事,现在WEB/移动端/Liunx都很流行分离式开发,界面一套,核心一套,你可以尝试一下
  相关解决方案