QT线程间阻塞通信

梦竹 2013-12-03 11:34:14
最近在研究QT线程间同步问题,遇到了如下问题:
启动一个界面线程uiThread和一个工作线程workThread
因为工作线程中不能弹出对话框,但是在遇到问题的时候需要进行弹窗提示,于是想使用uiThread来进行弹窗。
1.使用信号和槽:如果使用QueuedConnection和AutoConnection都可以实现让uiThread弹窗,但是这样做的问题是弹窗的时候线程还是在执行,希望他能够停下来等待用户指令。于是尝试使用DirectConnection,当workThread向uiThread发送信号的时候就崩溃了。
2.信号和槽不行了,于是想到事件机制,同样的,使用postEvent可以在两个线程之间发送事件,但是不能阻塞,使用sendEvent直接崩溃,提示不能向属于其他线程的对象发送信号。

请问各位大神有什么方法能够实现两个线程之间的阻塞通信?
...全文
489 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
wjlsmail 2013-12-13
  • 打赏
  • 举报
回复
std::mutex m; std::condition_variable cv; 与 QMutex Mutex; QWaitCondition WaitCond; 类似。 建议Qt中用后者,可移植性好一点。
masterz 2013-12-08
  • 打赏
  • 举报
回复
masterz 2013-12-08
  • 打赏
  • 举报
回复
QT自己也有类似的机制
#include <QWaitCondition>
#include <QMutex>
#include <QMutexLocker>
QMutex mutex;
QWaitCondition waitobj;
//        std::unique_lock<std::mutex> lk(m);
//        cv.wait(lk);
        QMutexLocker locker(&mutex);
        waitobj.wait(&mutex);

	QMutexLocker locker(&mutex);
    waitobj.wakeOne();
masterz 2013-12-07
  • 打赏
  • 举报
回复
贴个简单的例子,用到了C++ 2011 ######pro file QT += core gui CONFIG += c++11 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = qtgui TEMPLATE = app SOURCES += main.cpp\ mainwindow.cpp HEADERS += mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QThread>
#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
    virtual void paintEvent(QPaintEvent*);
public slots:
    void onRequestInput(QString prompt);
};
class WorkerThread : public QThread{
    Q_OBJECT
public:
    void run();
signals:
    void requestInput(QString prompt);
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include <QtGui/QPainter>
#include <QTime>
#include <QApplication>
#include <QInputDialog>
#include <QLineEdit>
#include <condition_variable>
#include <mutex>
#include <QDebug>

std::mutex m;
std::condition_variable cv;
QString msg;

void WorkerThread::run() {
    emit requestInput("Enter some message for WorkerThread!");
    qDebug() << QString("Current time: ") << QTime::currentTime() <<QString("in thread ")
             <<QThread::currentThreadId() << " waiting for input\n";
    {
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk);
    }
    qDebug() << "Got input: "<< msg;
}


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
}

MainWindow::~MainWindow()
{
    
}
void MainWindow::paintEvent( QPaintEvent* )
{
QTime now=QTime::currentTime();
QPainter painter(this);
painter.begin(this);
QRect rc = QRect(10, 10, 180, 20);
qint64 pid= QCoreApplication::applicationPid () ;
QString msg = now.toString();
msg.append(" process id: ");
msg.append( QString::number(pid));
painter.drawText(rc, msg);
painter.end();
}

void MainWindow::onRequestInput(QString prompt){
    bool ok;
    msg = QInputDialog::getText(this, tr("masterz:Enter input"),prompt, QLineEdit::Normal,"", &ok);
    cv.notify_one();
}
//main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    WorkerThread thread;
    w.connect(&thread,SIGNAL(requestInput(const QString&)),SLOT(onRequestInput(const QString&)) );
    thread.start();
    return a.exec();
}
梦竹 2013-12-03
  • 打赏
  • 举报
回复
这个真没有人知道么
本资源设置1个资源分,您可以下载作为捐献。 如果您有Git,还可以从http://www.goldenhawking.org:3000/goldenhawking/zoom.pipeline直接签出最新版本 (上一个版本“一种可伸缩的全异步C/S架构服务器实现”是有问题的,现在已经完成更改)。 服务由以下几个模块组成. 1、 网络传输模块。负责管理用于监听、传输的套接字,并控制数据流在不同线程中流动。数据收发由一定规模的线程池负责,实现方法完全得益于Qt线程事件循环。被绑定到某个Qthread上的Qobject对象,其信号-槽事件循环由该线程负责。这样,便可方便的指定某个套接字对象使用的线程。同样,受惠于Qt的良好封装,直接支持Tcp套接字及SSL套接字,且在运行时可动态调整。(注:编译这个模块需要Qt的SSL支持,即在 configure 时加入 -openssl 选项) 2、 任务流水线模块。负责数据的处理。在计算密集型的应用中,数据处理负荷较重,需要和网络传输划分开。基于普通线程池的处理模式,也存在队列阻塞的问题——若干个客户端请求的耗时操作,阻塞了其他客户端的响应,哪怕其他客户端的请求很短时就能处理完毕,也必须排队等待。采用流水线线程池避免了这个问题。每个客户端把需要做的操作进行粒度化,在一个环形的队列中,线程池对单个客户端,每次仅处理一个粒度单位的任务。单个粒度单位完成后,该客户端的剩余任务便被重新插入到队列尾部。这个机制保证了客户端的整体延迟较小。 3、 服务集群管理模块。该模块使用了网络传输模块、任务流水线模块的功能,实现了跨进程的服务器ßà服务器链路。在高速局域网中,连接是快速、稳定的。因此,该模块被设计成一种星型无中心网络。任意新增服务器节点选择现有服务器集群中的任意一个节点,接入后,通过广播自动与其他服务器节点建立点对点连接。本模块只是提供一个服务器到服务器的通信隧道,不负责具体通信内容的解译。对传输内容的控制,由具体应用决定。 4、 数据库管理模块。该模块基于Qt的插件式数据库封装QtSql。数据库被作为资源管理,支持在多线程的条件下,使用数据库资源。 5、 框架界面。尽管常见的服务运行时表现为一个后台进程,但为了更好的演示服务器的功能,避免繁琐的配置,还是需要一个图形界面来显示状态、设置参数。本范例中,界面负责轮训服务器的各个状态,并设置参数。设置好的参数被存储在一个ini文件中,并在服务开启时加载。 6、应用专有部分模块。上述1-4共四个主要模块均是通用的。他们互相之没有形成联系,仅仅是作为一种资源存在于程序的运行时(Runtime)之中。应用专有部分模块根据具体任务需求,灵活的使用上述资源,以实现功能。在范例代码中,实现了一种点对点的转发机制。演示者虚拟出一些工业设备,以及一些操作员使用的客户端软件。设备与客户端软件在成功认证并登录后,需要交换数据。改变这个模块的代码,即可实现自己的功能。
博客地址:https://blog.csdn.net/weixin_41749063/article/details/104023987 摘要: ## 1.简介 其实Qt网络模块中自带的[QTcpsocket](https://doc.qt.io/archives/qt-5.6/qtcpsocket.html)已经封装的很好了,避免了用原始套接字编程繁琐的过程,不过大部分应用场景我们希望将收发数据 运行在一个单独的线程,不阻塞界面或其他线程。所以结合Qt自带的QThread类 简单的封装了一下QTcpsocket,使其工作 在单独线程,并加入了心跳和断线重连机制。 ## 2.EasyClient类说明 由于接触QT不是很长,所以写的不是很好,可能里边也有Bug,不过觉得这个思路应该是可行的。封装的比较简单,若有问题完全可以自己改改。主要提供一个思路就是的将一个继承自QObject的子类转移到一个线程,使其在这个线程里进行事件循环,开一个定时器用于发送心跳和重连。 经过采坑发现,定时器的开和关需放在实例化EasyClient子类的那个线程(下面称之为主线程),不能在事件循环线程中(下面称之为子线程中)否则会有错。实例化QTcpsock需要在 子线程中进行,否则会出现无法正常通信的现象。 使用时只需要实例化一个EasyClient的子类,重写SendHeartBeat()和DisPoseReceiveData()两个纯虚函数,SendHeartBeat()决定发什么内容作为心跳指令,当有数据可读时会全部读入,只需要在DisPoseReceiveData()做处理即可。.

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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