qt怎么使用win thread实现多线程通信?

maliang351 2014-06-03 09:26:16
近来做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。
...全文
691 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
inurlcn 2014-06-11
  • 打赏
  • 举报
回复
pthred
l4kangaxx 2014-06-05
  • 打赏
  • 举报
回复
引用 10 楼 maliang351 的回复:
[quote=引用 9 楼 lion_kangaxx 的回复:] 使用posix标准的线程函数吧 编译的时候记得加上 -lpthread
额,我觉得这种做法也还是不行。因为用qt做界面显示就必须要和qt打交道,如果用非qt的线程(win/ posix),那估计就完全脱离qt了。qt的信号槽机制是肯定不能再使用了,这么做界面就难度太大了[/quote] 没事,现在WEB/移动端/Liunx都很流行分离式开发,界面一套,核心一套,你可以尝试一下
maliang351 2014-06-05
  • 打赏
  • 举报
回复
引用 9 楼 lion_kangaxx 的回复:
使用posix标准的线程函数吧 编译的时候记得加上 -lpthread
额,我觉得这种做法也还是不行。因为用qt做界面显示就必须要和qt打交道,如果用非qt的线程(win/ posix),那估计就完全脱离qt了。qt的信号槽机制是肯定不能再使用了,这么做界面就难度太大了
l4kangaxx 2014-06-05
  • 打赏
  • 举报
回复
使用posix标准的线程函数吧 编译的时候记得加上 -lpthread
maliang351 2014-06-05
  • 打赏
  • 举报
回复
引用 11 楼 lion_kangaxx 的回复:
[quote=引用 10 楼 maliang351 的回复:] [quote=引用 9 楼 lion_kangaxx 的回复:] 使用posix标准的线程函数吧 编译的时候记得加上 -lpthread
额,我觉得这种做法也还是不行。因为用qt做界面显示就必须要和qt打交道,如果用非qt的线程(win/ posix),那估计就完全脱离qt了。qt的信号槽机制是肯定不能再使用了,这么做界面就难度太大了[/quote] 没事,现在WEB/移动端/Liunx都很流行分离式开发,界面一套,核心一套,你可以尝试一下[/quote] 好的,我的设计思路也是界面和核心分开,正在摸索中。
maliang351 2014-06-04
  • 打赏
  • 举报
回复
引用 3 楼 dext 的回复:
其实也没有那么复杂了,只需要使用 LPVOID lpParamter 传入一个指针就行了。
你的意思是:子线程收到了数据,通过LPVOID lpParamter回传给主线程? 如果是这样的话,那主线程就要用轮询的方式不断访问某个标志位,用以确定子线程是否收到了数据。这样做的话主线程效率不高。最好的方式还是使用信号槽机制(类似中断触发)从子线程接收数据比较好。
「已注销」 2014-06-04
  • 打赏
  • 举报
回复
PostThreadMessage孩子
maliang351 2014-06-04
  • 打赏
  • 举报
回复
引用 6 楼 nlstone 的回复:
你直接使用Windows API, 在一个全局函数里当然是没有办法直接使用信号、槽的。(信号、槽都需要QObject支持) 你既然在练习Windows API,那就使用Windows的线程相关的同步、互斥(EnterCriticalSection, Event之类的) 使用QThread的时候用Qt的信号槽 在Win32下QThread并不复杂,你可以很容易看到源码是如何调用Windows API的,就和你现在做的一样。
恩,我也发现使用win32 thread无法实现线程间通信,所有还是使用了qt的QThread。 但是,我在使用的过程中又遇到了一个问题,子线程无法正常退出,我最后发现的原因是:子线程使用while循环不停的recvfrom(udp接收数据),这个recvfrom函数会导致线程阻塞,从而子线程无法退出。那么,在socket通信时,怎么处理数据接收比较好? 我将recvfrom改成了非阻塞模式,这样线程可以正常结束,但是感觉这种方法不好,因为没有数据到达时,recvfrom会返回一个错误码10035(意思就是缓存区无数据可读)。查了下,这个10035只能算异常,并不能算错误,但是这个10035就不需要处理一下吗?不知道还有木有其他方法。
nlstone 2014-06-04
  • 打赏
  • 举报
回复
你直接使用Windows API, 在一个全局函数里当然是没有办法直接使用信号、槽的。(信号、槽都需要QObject支持) 你既然在练习Windows API,那就使用Windows的线程相关的同步、互斥(EnterCriticalSection, Event之类的) 使用QThread的时候用Qt的信号槽 在Win32下QThread并不复杂,你可以很容易看到源码是如何调用Windows API的,就和你现在做的一样。
dbzhang800 2014-06-04
  • 打赏
  • 举报
回复
引用 4 楼 maliang351 的回复:
[quote=引用 3 楼 dext 的回复:] 其实也没有那么复杂了,只需要使用 LPVOID lpParamter 传入一个指针就行了。
你的意思是:子线程收到了数据,通过LPVOID lpParamter回传给主线程? 如果是这样的话,那主线程就要用轮询的方式不断访问某个标志位,用以确定子线程是否收到了数据。这样做的话主线程效率不高。最好的方式还是使用信号槽机制(类似中断触发)从子线程接收数据比较好。[/quote] 你太高估信号和槽了,跨线程的信号槽本身是通过Qt的事件系统实现的,事件系统就是一个循环在不停地轮询。要类似中断的话,你还是需要用mutex等东西
maliang351 2014-06-03
  • 打赏
  • 举报
回复
你好,我的signal的确是Widget的信号, class Widget : public QWidget { //static DWORD WINAPI threadInit(LPVOID lpParamter); } 你说QWidget是线程不安全的,那么它的信号不应该在子线程中使用,这一点我学习了。 由于我刚接触qt,对你说的两点注意不懂,能否稍加解释一下。 另外,我直接用系统线程API,感觉无法使用信号槽机制,更别谈跨线程,请问你有什么好的方法吗?
dbzhang800 2014-06-03
  • 打赏
  • 举报
回复
首先,你要分清:你那个dataReady到底是谁的成员函数,你又是如何调用其他类的成员函数的? 其次,你要明白:Qt的线程间通讯之所以可以通过(queue方式)信号槽进行通讯,其原因在于,Qt的事件系统是线程安全的。而你自己写的线程内连基本Qt的事件循环系统都无法启动,所以不要鲁莽地使用信号槽进行通讯的。 再次,你要清楚,QWidget及其派生类,都不是线程安全的,所以如果你的dataReady是他们的信号,你是不应该在次线程使用的。 注意:如果你: 1. 直接用系统线程API,而非QtAPI 2. 对Qt事件系统没有透彻的理解(也是不明白queue方式信号槽) 那么你最好不要碰,跨线程的信号槽。(因为即使在使用QThread的情况下,非常非常多的用户都不能正确使用跨线程的信号槽)
dext 2014-06-03
  • 打赏
  • 举报
回复
其实也没有那么复杂了,只需要使用 LPVOID lpParamter 传入一个指针就行了。

16,240

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧