近来做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的,就和你现在做的一样。
------解决方案--------------------
没事,现在WEB/移动端/Liunx都很流行分离式开发,界面一套,核心一套,你可以尝试一下